Python 是否有方法将先前计算的行值与数据帧中不同列的总和一起使用?
我有以下数据帧:Python 是否有方法将先前计算的行值与数据帧中不同列的总和一起使用?,python,pandas,dataframe,Python,Pandas,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
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函数进行计算,但这不起作用,如果有人能帮我找到正确的方向,那就太好了。如果你想表达这个函数
B[i] = (A[i-1] * 5 + A[i])/6
B[i] = (B[i-1] * 5 + A[i])/6
你的轮班安排是对的
B=((A.shift(1)*5)+A)/6
B.iat[0]=A.iat[0]
但是,如果要表示递归函数
B[i] = (A[i-1] * 5 + A[i])/6
B[i] = (B[i-1] * 5 + A[i])/6
然后,正如另一个答案所指出的那样,您不能使用矢量化的pandas操作,只能使用普通的Python代码进行计算。您可以在数据帧中循环并设置列
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
通过一些数学运算,我们可以将此递归公式转化为几何级数,如:
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
其中,窗口是并对应于代码中的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
我们可以定义一个函数
fast\u 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())
对
90000行的样本数据帧进行性能测试
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)
移位是否应该是A.shift(-1)
。B2是B1和A2的函数,而不是A1和A2。否,shift(1)
将所有值向前移位。因此A.shift(1)
的第一个元素是nan
,第二个元素是A[0]
,但是检查他写的计算,它看起来应该是向后移动的。这没有像预期的那样起作用,只是尝试了一下:df[“B”]=((df[“B”].shift(1)*5)+df[“A”)/6
。B2应该在计算中取上一个B1值。显然,循环需要时间,效率不高。是的,但列的每个值都取决于它自己的上一个值,因此我看不到实现shift
的方法。请随意提供更有效的答案。这给了我以下错误:文件“pandas\\ libs\index.pyx”,第96行,在pandas中。\ libs.index.IndexEngine.set\值文件“pandas\\ libs\index.pyx”,第107行,在pandas中。\ libs.index.IndexEngine.set\值文件“pandas\\ libs\index.pyx”,第595行,在pandas._libs.index.convert_scalar ValueError:无法将nan分配给整数系列
您可以检查df.dtypes的输出吗
?或者在我的代码前面加上一行df=df.astype('float64')
。即使我也找不到比循环更好的方法。无法使用shift和cumsum:/解决此问题。我觉得这没问题。你不能真正使用shift
,因为下一个值取决于上一个值的计算等等。那么这就是问题的结束;)@AnuragDhadse你什么意思:)
?@Tenzin接受这个答案,如果它有效的话,否则我们又花了宝贵生命的一个小时df[“B”]=(df.A.expansing().apply(lambda s:(s*((5/6)**np arange(len(s))[:-1])。sum()/6+(5/6)**s.size*s.iloc[0])给出:name错误:name'np不是defined@Tenzin对在你分享的问题的第一个版本中,没有NaN
,但我知道它被添加了。要解决这个问题,您可以在NaN
s中预先填入0:df.A=df.A.fillna(0)
,然后填入上面的代码。