不是一个特别容易解决的问题,但听起来你想要做类似的事情
df['rv'] = np.nan
for i in range(len(df)):
j = i
s = 0
while j >= 0 and s < 5:
s += df['distance'].loc[j]
j -= 1
if s >= 5:
df['rv'].loc[i] = df['velocity'][j+1:i+1].mean()
Update :自从这个回答以来,OP表示他们想要一个"valid Pandas solution (e.g. without loops)" . 如果我们认为这意味着他们想要比上述更高效的东西,那么,或许讽刺地给出评论,首先想到的优化是避免数据框架,除非需要:
l = len(df)
a = np.empty(l)
d = df['distance'].values
v = df['velocity'].values
for i in range(l):
j = i
s = 0
while j >= 0 and s < 5:
s += d[j]
j -= 1
if s >= 5:
a[i] = v[j+1:i+1].mean()
df['rv'] = a
此外,正如@JohnE所建议的那样,numba很快就会进一步优化 . 虽然它对上面的第一个解决方案没有太大作用,但第二个解决方案可以用开箱即用的装饰进行装饰,并立即带来好处 . 对所有三种解决方案进行基准测试
pd.DataFrame({'velocity': 50*np.random.random(10000), 'distance': 5*np.random.rand(10000)})
我得到以下结果:
Method Benchmark
-----------------------------------------------
Original data frame based 4.65 s ± 325 ms
Pure numpy array based 80.8 ms ± 9.95 ms
Jitted numpy array based 766 µs ± 52 µs
即使是看上去无辜的人也足以甩掉numba;如果我们摆脱它,而不是去
@numba.jit
def numba_example():
l = len(df)
a = np.empty(l)
d = df['distance'].values
v = df['velocity'].values
for i in range(l):
j = i
s = 0
while j >= 0 and s < 5:
s += d[j]
j -= 1
if s >= 5:
for k in range(j+1, i+1):
a[i] += v[k]
a[i] /= (i-j)
df['rv'] = a
然后基准降低到158μs±8.41μs .
现在,如果您碰巧了解 df['distance'] 的结构,可以进一步优化 while 循环 . (例如,如果值总是远低于5,那么从尾部剪切累积总和会更快,而不是重新计算所有内容 . )