Saj*_*han 12 python sum time-series pandas
假设我有以下数据框
Date, A
2014-11-21 11:00:00, 1
2014-11-21 11:03:00, 4
2014-11-21 11:04:00, 1
2014-11-21 11:05:00, 2
2014-11-21 11:07:00, 4
2014-11-21 11:08:00, 1
2014-11-21 11:12:00, 1
2014-11-21 11:13:00, 2
Run Code Online (Sandbox Code Playgroud)
第一列是datetime对象,第二列是整数.我想要的是计算每行最后五分钟的'A'列的总和.
作为行的示例 2014-11-21 11:12:00, 1,列'A'的总和将是2(1 + 1),并且该行的列'A'的总和2014-11-21 11:05:00, 2将是7(2 + 1 + 4).重要的是时间窗口的过去行数(5分钟)对于每一行都不相同(因为时间序列是不规则的).
如何使用pandas中的rolling_sum方法获取列'A'的最后五分钟总和?提前致谢.
unu*_*tbu 16
一般来说,如果日期完全是任意的,我认为你会被迫for-loop在行上使用Python 或使用df.apply,(在引擎盖下,也使用Python循环.)
但是,如果您的日期共享一个共同频率,如上所述,那么有一个技巧应该比使用快得多df.apply:根据公共频率扩展时间序列 - 在这种情况下,1分钟 - 填写NaNs用零,然后调用rolling_sum:
In [279]: pd.rolling_sum(df.set_index(['Date']).asfreq('1T').fillna(0), window=5, min_periods=1).reindex(df['Date'])
Out[279]:
A
Date
2014-11-21 11:00:00 1
2014-11-21 11:03:00 5
2014-11-21 11:04:00 6
2014-11-21 11:05:00 7
2014-11-21 11:07:00 11
2014-11-21 11:08:00 8
2014-11-21 11:12:00 2
2014-11-21 11:13:00 3
Run Code Online (Sandbox Code Playgroud)
当然,如果你愿意接受足够小的粒度,任何时间序列都有一个共同的频率,但是所需的大小df.asfreq(...)可能会使这个技巧变得不切实际.
以下是使用更一般方法的示例df.apply.请注意,调用searchsorted依赖df['Date']于按排序顺序.
import numpy as np
import pandas as pd
df = pd.read_csv('data', parse_dates=[0], sep=',\s*')
start_dates = df['Date'] - pd.Timedelta(minutes=5)
df['start_index'] = df['Date'].values.searchsorted(start_dates, side='right')
df['end_index'] = np.arange(len(df))
def sum_window(row):
return df['A'].iloc[row['start_index']:row['end_index']+1].sum()
df['rolling_sum'] = df.apply(sum_window, axis=1)
print(df[['Date', 'A', 'rolling_sum']])
Run Code Online (Sandbox Code Playgroud)
产量
Date A rolling_sum
0 2014-11-21 11:00:00 1 1
1 2014-11-21 11:03:00 4 5
2 2014-11-21 11:04:00 1 6
3 2014-11-21 11:05:00 2 7
4 2014-11-21 11:07:00 4 11
5 2014-11-21 11:08:00 1 8
6 2014-11-21 11:12:00 1 2
7 2014-11-21 11:13:00 2 3
Run Code Online (Sandbox Code Playgroud)
这是一个比较df.asfreq技巧与调用的基准df.apply:
import numpy as np
import pandas as pd
df = pd.read_csv('data', parse_dates=[0], sep=',\s*')
def big_df(df):
df = df.copy()
for i in range(7):
dates = df['Date'] + pd.Timedelta(df.iloc[-1]['Date']-df.iloc[0]['Date']) + pd.Timedelta('1 minute')
df2 = pd.DataFrame({'Date': dates, 'A': df['A']})
df = pd.concat([df, df2])
df = df.reset_index(drop=True)
return df
def using_apply():
start_dates = df['Date'] - pd.Timedelta(minutes=5)
df['start_index'] = df['Date'].values.searchsorted(start_dates, side='right')
df['end_index'] = np.arange(len(df))
def sum_window(row):
return df['A'].iloc[row['start_index']:row['end_index']+1].sum()
df['rolling_sum'] = df.apply(sum_window, axis=1)
return df[['Date', 'rolling_sum']]
def using_asfreq():
result = (pd.rolling_sum(
df.set_index(['Date']).asfreq('1T').fillna(0),
window=5, min_periods=1).reindex(df['Date']))
return result
Run Code Online (Sandbox Code Playgroud)
In [364]: df = big_df(df)
In [367]: %timeit using_asfreq()
1000 loops, best of 3: 1.21 ms per loop
In [368]: %timeit using_apply()
1 loops, best of 3: 208 ms per loop
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10654 次 |
| 最近记录: |