gpt4 book ai didi

python - Pandas 应用使用最小/最大在可变滚动窗口上执行缓慢

转载 作者:行者123 更新时间:2023-11-28 18:23:26 25 4
gpt4 key购买 nike

我正在计算一个时间序列的值(通过 myvalues 表示)。下面的代码标识事件发生的位置 (cross_indices),然后计算最后 8 个事件 (n_crosses)。 Series max_lookback 中设置了第 8 个交叉相对于每一行时间的索引。

设置 max_lookback 全部代码只需要大约 0.5 秒。但是,当我运行 pd.apply() 以获取从当前索引到 max_lookbackmyvalues 的最小值和最大值时,代码需要 ~运行 22 秒。

我认为 apply() 应该比 for 循环更快地遍历行。为什么代码的执行时间如此之长,我如何才能显着加快它的速度?

程序输出为

total time of minmax is 22.469 seconds

total runtime is 22.93 seconds

import pandas as pd
import numpy as np
import timeit

complete_start = timeit.default_timer()
indices = pd.Series( range(20000), name='Index')
sample_from = np.append(np.zeros(9), 1) #10% odds of selecting 1
cross = pd.Series( np.random.choice( sample_from, size=len(indices) ), name='Cross' )
#cross = pd.Series(
cross_indices = np.flatnonzero( cross )
n_crosses = 8

def set_max_lookback(index):
sub = cross_indices[ cross_indices <= index ]
#get integer index where crosses occurred

if len( sub ) < n_crosses:
return int( 0 )

return int( sub[ len(sub) - n_crosses ] )

max_lookback = pd.Series( indices.apply( set_max_lookback ), name='MaxLookback' )

start = timeit.default_timer()
myvalues = pd.Series( np.random.randint(-100,high=100, size=len(indices) ), name='Random' )

def minmax_of_zero_crosses(index):

sub = myvalues.iloc[ range( max_lookback[index], index+1 ) ]
return ( sub.min(), sub.max() )

minmax_as_tuple_series = pd.Series( indices.apply( minmax_of_zero_crosses ), name='Min' )
minmax_df = pd.DataFrame( minmax_as_tuple_series.tolist() )
minmax_df.columns = [ 'Min', 'Max' ]
maxz = minmax_df['Max']
minz = minmax_df['Min']
end = timeit.default_timer()
print('total time of minmax is ' + str(end-start) + ' seconds.')
complete_end = timeit.default_timer()
print('total runtime is ' + str(complete_end-complete_start) + ' seconds.')

编辑 1

根据 Mitch 的评论,我仔细检查了 max_lookback 设置。使用 n_crosses=3,您可以看到为第 19,995 行选择了正确的索引 19,981。图片上没有显示的列标签是 index、myvalues、cross、max_lookback。

df = pd.DataFrame([myvalues, cross, max_lookback, maxz, minz ] ).transpose()
print(df.tail(n=60))

n_crosses=3

以图像为例,对于第 19,999 行,我想在第 19,981 行(max_lookback 列)和 19,999 之间找到我的值的最小值/最大值,即 -95 和 +97。

最佳答案

apply 实际上通常根本不是一个非常有效的解决方案,因为它实际上只是一个底层的 for 循环本身。

矢量化方法:

indices = pd.Series(range(20000))
sample_from = np.append(np.zeros(9), 1) #10% odds of selecting 1
cross = pd.Series(np.random.choice(sample_from, size=indices.size))
myvalues = pd.DataFrame(dict(Random=np.random.randint(-100,
100,
size=indices.size)))

n_crosses = 8
nonzeros = cross.nonzero()[0]
diffs = (nonzeros-np.roll(nonzeros, n_crosses-1)).clip(0)
myvalues['lower'] = np.nan
myvalues.loc[nonzeros, 'lower'] = diffs
myvalues.lower = ((myvalues.index.to_series() - myvalues.lower)
.fillna(method='ffill')
.fillna(0).astype(np.int))
myvalues.loc[:(cross.cumsum() < n_crosses).sum()+1, 'lower'] = 0

reducer = np.empty((myvalues.shape[0]*2,), dtype=myvalues.lower.dtype)
reducer[::2] = myvalues.lower.values
reducer[1::2] = myvalues.index.values + 1
myvalues.loc[myvalues.shape[0]] = [0,0]
minmax_df = pd.DataFrame(
{'min':np.minimum.reduceat(myvalues.Random.values, reducer)[::2],
'max':np.maximum.reduceat(myvalues.Random.values, reducer)[::2]}
)

这会产生与您当前解决方案相同的最小/最大 DataFrame。基本思想是为 myvalues 中的每个索引生成最小/最大边界,然后使用 ufunc.reduceat计算那些最小值/最大值。

在我的机器上,您当前的解决方案每个循环需要大约 8.1 s,而上面的解决方案每个循环需要大约 7.9 ms,加速大约 1025%。

关于python - Pandas 应用使用最小/最大在可变滚动窗口上执行缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43331649/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com