有没有一种方法可以使用以前计算的行值与Pandas Dataframe中不同列的总和?

qnyhuwrf  于 2023-04-10  发布在  其他
关注(0)|答案(4)|浏览(121)

我有以下dataframe:

A          B
2021-05-19 07:00:00  Nan        Nan
2021-05-19 07:30:00  0.00       Nan
2021-05-19 08:00:00  0.00       Nan
2021-05-19 08:30:00  0.00       Nan
2021-05-19 09:00:00  19.91      Nan
2021-05-19 09:30:00  0.11       Nan
2021-05-19 10:00:00  0.00       Nan
2021-05-19 10:30:00  22.99      Nan
2021-05-19 11:00:00  0.00       Nan

要求:

A          B
2021-05-19 07:00:00  Nan        0.00
2021-05-19 07:30:00  0.00       0.00
2021-05-19 08:00:00  0.00       0.00
2021-05-19 08:30:00  0.00       0.00
2021-05-19 09:00:00  19.91      3.32
2021-05-19 09:30:00  0.11       2.78
2021-05-19 10:00:00  0.00       2.32
2021-05-19 10:30:00  22.99      5.76
2021-05-19 11:00:00  0.00       4.80

B列的计算:

B1 = A1
B2 = ((B1*5)+A2)/6
B3 = ((B2*5)+A3)/6
B4 = ((B3*5)+A4)/6
etc.

我已经尝试过在Python中使用shift函数进行计算,但这不起作用,如果有人能在正确的方向上帮助我,那就太好了。

xqnpmsa8

xqnpmsa81#

我们可以定义一个函数fast_sum来执行所需的计算,然后使用称为即时编译的技术,将此函数编译为机器代码,以便它可以以类似C的速度更有效地运行。

import numba

@numba.jit(nopython=True)
def fast_sum(a):
    b = np.zeros_like(a)
    b[0] = a[0]
    for i in range(1, len(a)):
        b[i] = (b[i - 1] * 5 + a[i]) / 6 
    return b

df['B'] = fast_sum(df['A'].fillna(0).to_numpy())
A         B
2021-05-19 07:00:00   0.00  0.000000
2021-05-19 07:30:00   0.00  0.000000
2021-05-19 08:00:00   0.00  0.000000
2021-05-19 08:30:00   0.00  0.000000
2021-05-19 09:00:00  19.91  3.318333
2021-05-19 09:30:00   0.11  2.783611
2021-05-19 10:00:00   0.00  2.319676
2021-05-19 10:30:00  22.99  5.764730
2021-05-19 11:00:00   0.00  4.803942

90000行的示例 Dataframe 进行性能测试

df = pd.concat([df] * 10000, ignore_index=True)

%%timeit
df['B'] = fast_sum(df['A'].fillna(0).to_numpy())
# 1.62 ms ± 93.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
eufgjt7s

eufgjt7s2#

您可以遍历DataFrame并设置列B,因为B的每个值都取决于它自己以前的值。

for i, date in enumerate(df.index):
    if i==0:
        df.at[date, "B"] = 0
    else:
        df.at[date, "B"] = (df["B"].iat[i-1]*5+df.at[date, "A"])/6
df
>>
                         A         B
2021-05-19 07:00:00   0.00  0.000000
2021-05-19 07:30:00   0.00  0.000000
2021-05-19 08:00:00   0.00  0.000000
2021-05-19 08:30:00   0.00  0.000000
2021-05-19 09:00:00  19.91  3.318333
2021-05-19 09:30:00   0.11  2.783611
2021-05-19 10:00:00   0.00  2.319676
2021-05-19 10:30:00  22.99  5.764730
2021-05-19 11:00:00   0.00  4.803942
eoxn13cs

eoxn13cs3#

通过一些数学运算,我们可以将这个递归公式转化为如下的几何级数:

df["B"] = (df.A
             .fillna(0)
             .expanding()
             .apply(lambda s: (1/6)*(s * ((5/6) ** np.arange(len(s))[::-1])).sum() + (5/6)**s.size*s.iloc[0]))

它相当于

N := window.size

B_j = (5/6)^(N-1) A_1 + (1/6) \sum_{j=2}^{N} (5/6)^(N-j) A_j

其中window是expanding,对应于代码中的s。然而,在代码中,我们将A_1与其他值相加,从而从中取1/6;所以我们把剩余的5/6相加,因此前面是(5/6)^N(而不是N-1);我们还将A中的NaN s设置为0,以防止它们传播。
得到

A         B
2021-05-19 07:00:00    NaN  0.000000
2021-05-19 07:30:00   0.00  0.000000
2021-05-19 08:00:00   0.00  0.000000
2021-05-19 08:30:00   0.00  0.000000
2021-05-19 09:00:00  19.91  3.318333
2021-05-19 09:30:00   0.11  2.783611
2021-05-19 10:00:00   0.00  2.319676
2021-05-19 10:30:00  22.99  5.764730
2021-05-19 11:00:00   0.00  4.803942
0yg35tkg

0yg35tkg4#

如果你想表达功能

B[i] = (A[i-1] * 5 + A[i])/6

你的转变方向是正确的

B = ((A.shift(1)*5)+A)/6
B.iat[0] = A.iat[0]

但是,如果要表达递归函数

B[i] = (B[i-1] * 5 + A[i])/6

然后你不能使用向量化的pandas操作,只能使用普通的Python代码来计算,正如另一个答案所指出的那样。

相关问题