Pandas 滚动时间 window 按天而不是单独的行
Pandas rolling time window by days instead of individual rows
我有一个大型数据集,我需要计算 N 天滚动时间 window 的一些统计数据。每天有多个条目。我需要计算 N 天时间范围内所有行的统计数据,即两端每天计算。
带时间偏移的pandas.DataFrame.rolling()方法差不多可以用了。此方法的时间偏移向后看以包括 N 天时间范围内的所有天,但向前看,window 按行滚动,即直到一天结束。
我已经编写了一个循环来执行此操作,但它在我的大型数据集上运行得非常慢。有没有一种有效的方法可以使用 rolling()、使用某种索引器或其他方式来做到这一点?
我需要计算的测试统计量是计数、均值和标准差。我修改后的例子:
#Create test dataframe:
import pandas as pd
l1=[1,2,3,4,5,6,7,8,9,10,11,12]
ts=[pd.Timestamp('2017-01-01'),
pd.Timestamp('2017-01-02'),
pd.Timestamp('2017-01-03'),
pd.Timestamp('2017-01-04'),
pd.Timestamp('2017-01-05'),
pd.Timestamp('2017-01-05'),
pd.Timestamp('2017-01-05'),
pd.Timestamp('2017-01-06'),
pd.Timestamp('2017-01-06'),
pd.Timestamp('2017-01-07'),
pd.Timestamp('2017-01-07'),
pd.Timestamp('2017-01-08')]
In [58]: df=pd.DataFrame({'t':ts, 'c':l1, 'm':l1, 's':l1}).set_index('t')
In [59]: df
Out[59]:
c m s
t
2017-01-01 1 1 1
2017-01-02 2 2 2
2017-01-03 3 3 3
2017-01-04 4 4 4
2017-01-05 5 5 5
2017-01-05 6 6 6
2017-01-05 7 7 7
2017-01-06 8 8 8
2017-01-06 9 9 9
2017-01-07 10 10 10
2017-01-07 11 11 11
2017-01-08 12 12 12
In [60]: df.rolling('3D').agg({'c':'count', 'm':'mean', 's':'std'})
Out[60]:
c m s
t
2017-01-01 1.0 1.0 NaN
2017-01-02 2.0 1.5 0.707107
2017-01-03 3.0 2.0 1.000000
2017-01-04 3.0 3.0 1.000000
2017-01-05 3.0 4.0 1.000000 #incorrect for day-end window boundary
2017-01-05 4.0 4.5 1.290994 #incorrect for day-end window boundary
2017-01-05 5.0 5.0 1.581139
2017-01-06 5.0 6.0 1.581139 #incorrect for day-end window boundary
2017-01-06 6.0 6.5 1.870829
2017-01-07 6.0 7.5 1.870829 #incorrect for day-end window boundary
2017-01-07 7.0 8.0 2.160247
2017-01-08 5.0 10.0 1.581139
但是根据以同一天的所有行结尾的 window 计算,结果将是:
c m s
t
2017-01-01 1.0 1.0 NaN
2017-01-02 2.0 1.5 0.707107
2017-01-03 3.0 2.0 1.000000
2017-01-04 3.0 3.0 1.000000
2017-01-05 5.0 5.0 1.581139 #This is what it should be
2017-01-05 5.0 5.0 1.581139 #This is what it should be
2017-01-05 5.0 5.0 1.581139
2017-01-06 6.0 6.5 1.870829 #This is what it should be
2017-01-06 6.0 6.5 1.870829
2017-01-07 7.0 8.0 2.160247 #This is what it should be
2017-01-07 7.0 8.0 2.160247
2017-01-08 5.0 10.0 1.581139
请注意,每一天的最后一行都是正确的,同一天所有其他行的答案都是正确的。
如果你的数据一直是正数,你可以滚动后变换:
# if your index is not always on the day, e.g. 2017-01-01 01:00:00
# use `pd.Grouper(freq='D')` instead of `level`
df.rolling('3D').sum().groupby(level='t').transform('max')
输出:
a
t
2017-01-01 1.0
2017-01-02 2.0
2017-01-03 3.0
2017-01-04 3.0
2017-01-05 5.0
2017-01-05 5.0
2017-01-05 5.0
2017-01-06 6.0
2017-01-06 6.0
2017-01-07 7.0
2017-01-07 7.0
2017-01-08 5.0
编辑:一般情况下,按天汇总并映射回来:
s = df.groupby(pd.Grouper(freq='D')).sum().rolling('3D').sum()
df.index.floor('D').to_series().map(s['a'])
输出:
t
2017-01-01 1.0
2017-01-02 2.0
2017-01-03 3.0
2017-01-04 3.0
2017-01-05 5.0
2017-01-05 5.0
2017-01-05 5.0
2017-01-06 6.0
2017-01-06 6.0
2017-01-07 7.0
2017-01-07 7.0
2017-01-08 5.0
Name: t, dtype: float64
我有一个大型数据集,我需要计算 N 天滚动时间 window 的一些统计数据。每天有多个条目。我需要计算 N 天时间范围内所有行的统计数据,即两端每天计算。
带时间偏移的pandas.DataFrame.rolling()方法差不多可以用了。此方法的时间偏移向后看以包括 N 天时间范围内的所有天,但向前看,window 按行滚动,即直到一天结束。
我已经编写了一个循环来执行此操作,但它在我的大型数据集上运行得非常慢。有没有一种有效的方法可以使用 rolling()、使用某种索引器或其他方式来做到这一点?
我需要计算的测试统计量是计数、均值和标准差。我修改后的例子:
#Create test dataframe:
import pandas as pd
l1=[1,2,3,4,5,6,7,8,9,10,11,12]
ts=[pd.Timestamp('2017-01-01'),
pd.Timestamp('2017-01-02'),
pd.Timestamp('2017-01-03'),
pd.Timestamp('2017-01-04'),
pd.Timestamp('2017-01-05'),
pd.Timestamp('2017-01-05'),
pd.Timestamp('2017-01-05'),
pd.Timestamp('2017-01-06'),
pd.Timestamp('2017-01-06'),
pd.Timestamp('2017-01-07'),
pd.Timestamp('2017-01-07'),
pd.Timestamp('2017-01-08')]
In [58]: df=pd.DataFrame({'t':ts, 'c':l1, 'm':l1, 's':l1}).set_index('t')
In [59]: df
Out[59]:
c m s
t
2017-01-01 1 1 1
2017-01-02 2 2 2
2017-01-03 3 3 3
2017-01-04 4 4 4
2017-01-05 5 5 5
2017-01-05 6 6 6
2017-01-05 7 7 7
2017-01-06 8 8 8
2017-01-06 9 9 9
2017-01-07 10 10 10
2017-01-07 11 11 11
2017-01-08 12 12 12
In [60]: df.rolling('3D').agg({'c':'count', 'm':'mean', 's':'std'})
Out[60]:
c m s
t
2017-01-01 1.0 1.0 NaN
2017-01-02 2.0 1.5 0.707107
2017-01-03 3.0 2.0 1.000000
2017-01-04 3.0 3.0 1.000000
2017-01-05 3.0 4.0 1.000000 #incorrect for day-end window boundary
2017-01-05 4.0 4.5 1.290994 #incorrect for day-end window boundary
2017-01-05 5.0 5.0 1.581139
2017-01-06 5.0 6.0 1.581139 #incorrect for day-end window boundary
2017-01-06 6.0 6.5 1.870829
2017-01-07 6.0 7.5 1.870829 #incorrect for day-end window boundary
2017-01-07 7.0 8.0 2.160247
2017-01-08 5.0 10.0 1.581139
但是根据以同一天的所有行结尾的 window 计算,结果将是:
c m s
t
2017-01-01 1.0 1.0 NaN
2017-01-02 2.0 1.5 0.707107
2017-01-03 3.0 2.0 1.000000
2017-01-04 3.0 3.0 1.000000
2017-01-05 5.0 5.0 1.581139 #This is what it should be
2017-01-05 5.0 5.0 1.581139 #This is what it should be
2017-01-05 5.0 5.0 1.581139
2017-01-06 6.0 6.5 1.870829 #This is what it should be
2017-01-06 6.0 6.5 1.870829
2017-01-07 7.0 8.0 2.160247 #This is what it should be
2017-01-07 7.0 8.0 2.160247
2017-01-08 5.0 10.0 1.581139
请注意,每一天的最后一行都是正确的,同一天所有其他行的答案都是正确的。
如果你的数据一直是正数,你可以滚动后变换:
# if your index is not always on the day, e.g. 2017-01-01 01:00:00
# use `pd.Grouper(freq='D')` instead of `level`
df.rolling('3D').sum().groupby(level='t').transform('max')
输出:
a
t
2017-01-01 1.0
2017-01-02 2.0
2017-01-03 3.0
2017-01-04 3.0
2017-01-05 5.0
2017-01-05 5.0
2017-01-05 5.0
2017-01-06 6.0
2017-01-06 6.0
2017-01-07 7.0
2017-01-07 7.0
2017-01-08 5.0
编辑:一般情况下,按天汇总并映射回来:
s = df.groupby(pd.Grouper(freq='D')).sum().rolling('3D').sum()
df.index.floor('D').to_series().map(s['a'])
输出:
t
2017-01-01 1.0
2017-01-02 2.0
2017-01-03 3.0
2017-01-04 3.0
2017-01-05 5.0
2017-01-05 5.0
2017-01-05 5.0
2017-01-06 6.0
2017-01-06 6.0
2017-01-07 7.0
2017-01-07 7.0
2017-01-08 5.0
Name: t, dtype: float64