使用Pandas tshift
非常棒。这很快!
df = pd.DataFrame(index=pd.date_range(pd.datetime(1970,1,1),pd.datetime(1970,2,1)))
df['data']=.5
%timeit df.sum()
#10000 loops, best of 3: 162 µs per loop
%timeit df.tshift(-1)
#1000 loops, best of 3: 307 µs per loop #x2 slower
但是当我在tshift
之后groupby
进行df = pd.DataFrame(index=pd.date_range(pd.datetime(1970,1,1),pd.datetime(1970,2,1)))
df['data']=.5
df['A'] = randint(0,2,len(df.index))
%timeit df.groupby('A').sum()
#100 loops, best of 3: 2.72 ms per loop
%timeit df.groupby('A').tshift(-1)
#10 loops, best of 3: 16 ms per loop #x6 slower!
时,它会放慢速度:
tshift
为什么n_A = 50
n_B = 5
index = pd.MultiIndex.from_product([arange(n_A),
arange(n_B),
pd.date_range(pd.datetime(1975,1,1),
pd.datetime(2010,1,1),
freq='5AS')],
names=['A', 'B', 'Year'])
df = pd.DataFrame(index=index)
df['data']=.5
%timeit df.reset_index(['A','B']).groupby(['A','B']).sum()
#100 loops, best of 3: 4.34 ms per loop
%timeit df.reset_index(['A','B']).groupby(['A','B']).tshift(-1, freq='5AS')
#10 loops, best of 3: 198 ms per loop # X44 slowdown.
在进行分组时会这么慢?有没有办法更快?
更新
我的实际使用案例更接近以下代码。我看到减速乘数的大小取决于组的数量。
n_A = 500
n_B = 50
...
%timeit df.reset_index(['A','B']).groupby(['A','B']).sum()
#10 loops, best of 3: 35.8 ms per loop
%timeit df.reset_index(['A','B']).groupby(['A','B']).tshift(-1, freq='5AS')
#1 loops, best of 3: 20.3 s per loop # X567 slowdown
然而,如果我们增加A和B组的数量:
{{1}}
我感到惊讶的是,随着团队人数的增加,经济增长放缓!有更聪明的方法吗?
答案 0 :(得分:5)
tshift
需要一个freq参数用于此用法(因为freq在分组时可能并且通常不常规),因此df.groupby('A').tshift(-1)
返回一个空帧(它为每个组提升,减慢它同样)。
In [44]: %timeit df.groupby('A').tshift(-1,'D')
100 loops, best of 3: 3.57 ms per loop
In [45]: %timeit df.groupby('A').sum()
1000 loops, best of 3: 1.02 ms per loop
除此之外,这个问题here正在等待shift(和tshift)的cythonized实现。这将使得与sum相提并论,这是cython化的。欢迎捐款!
使用您的第二个数据集(更大的组),您可以这样做:
In [59]: def f(df):
....: x = df.reset_index()
....: x['Year_ts'] = pd.DatetimeIndex(x['Year'])-pd.offsets.YearBegin(5)
....: return x.drop(['Year'],axis=1).rename(columns={'Year_ts' : 'Year'}).set_index(['A','B','Year'])
....:
In [60]: result = df.reset_index(['A','B']).groupby(['A','B']).tshift(-1,'5AS')
In [61]: %timeit df.reset_index(['A','B']).groupby(['A','B']).tshift(-1,'5AS')
1 loops, best of 3: 10.8 s per loop
In [62]: result2 = f(df)
In [63]: %timeit f(df)
1 loops, best of 3: 2.51 s per loop
In [64]: result.equals(result2)
Out[64]: True
因此,在groupby之外进行日期减法使得速度提高约4倍。而且(和缓存)是使分组tshift更快的第一步。