Sna*_*Gee 42 python time-series hierarchical-data pandas
我有一些分层数据,最终到时间序列数据,看起来像这样:
df = pandas.DataFrame(
{'value_a': values_a, 'value_b': values_b},
index=[states, cities, dates])
df.index.names = ['State', 'City', 'Date']
df
value_a value_b
State City Date
Georgia Atlanta 2012-01-01 0 10
2012-01-02 1 11
2012-01-03 2 12
2012-01-04 3 13
Savanna 2012-01-01 4 14
2012-01-02 5 15
2012-01-03 6 16
2012-01-04 7 17
Alabama Mobile 2012-01-01 8 18
2012-01-02 9 19
2012-01-03 10 20
2012-01-04 11 21
Montgomery 2012-01-01 12 22
2012-01-02 13 23
2012-01-03 14 24
2012-01-04 15 25
Run Code Online (Sandbox Code Playgroud)
我想对每个城市进行时间重新采样,所以就像这样
df.resample("2D", how="sum")
Run Code Online (Sandbox Code Playgroud)
会输出
value_a value_b
State City Date
Georgia Atlanta 2012-01-01 1 21
2012-01-03 5 25
Savanna 2012-01-01 9 29
2012-01-03 13 33
Alabama Mobile 2012-01-01 17 37
2012-01-03 21 41
Montgomery 2012-01-01 25 45
2012-01-03 29 49
Run Code Online (Sandbox Code Playgroud)
df.resample('2D', how='sum')
得到我,得到我
TypeError: Only valid with DatetimeIndex or PeriodIndex
Run Code Online (Sandbox Code Playgroud)
很公平,但我希望这可行:
>>> df.swaplevel('Date', 'State').resample('2D', how='sum')
TypeError: Only valid with DatetimeIndex or PeriodIndex
Run Code Online (Sandbox Code Playgroud)
在这一点上,我真的没有想法......有没有什么方法堆叠和拆散可能能够帮助我?
unu*_*tbu 39
pd.Grouper
允许您指定"目标对象的groupby指令".特别是,您可以使用它按日期分组,即使df.index
它不是DatetimeIndex
:
df.groupby(pd.Grouper(freq='2D', level=-1))
Run Code Online (Sandbox Code Playgroud)
在level=-1
讲述pd.Grouper
寻找在多指标的最后一个级别的日期.此外,您可以将其与索引中的其他级别值结合使用:
level_values = df.index.get_level_values
result = (df.groupby([level_values(i) for i in [0,1]]
+[pd.Grouper(freq='2D', level=-1)]).sum())
Run Code Online (Sandbox Code Playgroud)
它看起来有点尴尬,但using_Grouper
结果比我原来的建议快得多using_reset_index
:
import numpy as np
import pandas as pd
import datetime as DT
def using_Grouper(df):
level_values = df.index.get_level_values
return (df.groupby([level_values(i) for i in [0,1]]
+[pd.Grouper(freq='2D', level=-1)]).sum())
def using_reset_index(df):
df = df.reset_index(level=[0, 1])
return df.groupby(['State','City']).resample('2D').sum()
def using_stack(df):
# http://stackoverflow.com/a/15813787/190597
return (df.unstack(level=[0,1])
.resample('2D').sum()
.stack(level=[2,1])
.swaplevel(2,0))
def make_orig():
values_a = range(16)
values_b = range(10, 26)
states = ['Georgia']*8 + ['Alabama']*8
cities = ['Atlanta']*4 + ['Savanna']*4 + ['Mobile']*4 + ['Montgomery']*4
dates = pd.DatetimeIndex([DT.date(2012,1,1)+DT.timedelta(days = i) for i in range(4)]*4)
df = pd.DataFrame(
{'value_a': values_a, 'value_b': values_b},
index = [states, cities, dates])
df.index.names = ['State', 'City', 'Date']
return df
def make_df(N):
dates = pd.date_range('2000-1-1', periods=N)
states = np.arange(50)
cities = np.arange(10)
index = pd.MultiIndex.from_product([states, cities, dates],
names=['State', 'City', 'Date'])
df = pd.DataFrame(np.random.randint(10, size=(len(index),2)), index=index,
columns=['value_a', 'value_b'])
return df
df = make_orig()
print(using_Grouper(df))
Run Code Online (Sandbox Code Playgroud)
产量
value_a value_b
State City Date
Alabama Mobile 2012-01-01 17 37
2012-01-03 21 41
Montgomery 2012-01-01 25 45
2012-01-03 29 49
Georgia Atlanta 2012-01-01 1 21
2012-01-03 5 25
Savanna 2012-01-01 9 29
2012-01-03 13 33
Run Code Online (Sandbox Code Playgroud)
这里是一个标杆比较using_Grouper
,using_reset_index
,using_stack
在一个有5000行数据帧:
In [30]: df = make_df(10)
In [34]: len(df)
Out[34]: 5000
In [32]: %timeit using_Grouper(df)
100 loops, best of 3: 6.03 ms per loop
In [33]: %timeit using_stack(df)
10 loops, best of 3: 22.3 ms per loop
In [31]: %timeit using_reset_index(df)
1 loop, best of 3: 659 ms per loop
Run Code Online (Sandbox Code Playgroud)
use*_*356 14
使用堆栈/取消堆栈的替代方案
df.unstack(level=[0,1]).resample('2D', how='sum').stack(level=[2,1]).swaplevel(2,0)
value_a value_b
State City Date
Georgia Atlanta 2012-01-01 1 21
Alabama Mobile 2012-01-01 17 37
Montgomery 2012-01-01 25 45
Georgia Savanna 2012-01-01 9 29
Atlanta 2012-01-03 5 25
Alabama Mobile 2012-01-03 21 41
Montgomery 2012-01-03 29 49
Georgia Savanna 2012-01-03 13 33
Run Code Online (Sandbox Code Playgroud)
笔记:
ksi*_*ndi 10
这有效:
df.groupby(level=[0,1]).apply(lambda x: x.set_index('Date').resample('2D', how='sum'))
value_a value_b
State City Date
Alabama Mobile 2012-01-01 17 37
2012-01-03 21 41
Montgomery 2012-01-01 25 45
2012-01-03 29 49
Georgia Atlanta 2012-01-01 1 21
2012-01-03 5 25
Savanna 2012-01-01 9 29
2012-01-03 13 33
Run Code Online (Sandbox Code Playgroud)
如果Date列是字符串,则事先转换为datetime:
df['Date'] = pd.to_datetime(df['Date'])
Run Code Online (Sandbox Code Playgroud)
您需要该groupby()
方法,并为pd.Grouper
要在结果DataFrame中维护的MultiIndex的每个级别提供。然后,您可以应用选择的操作。
重新采样日期或时间戳的水平,你需要设置freq
与选择的频率参数-使用类似的方法pd.TimeGrouper()
赞成不赞成pd.Grouper()
与freq
参数设置。
这应该为您提供所需的DataFrame:
df.groupby([pd.Grouper(level='State'), pd.Grouper(level='City'), pd.Grouper(level='Date', freq='2D')]).sum()
Run Code Online (Sandbox Code Playgroud)
pandas文档中的“ 时间序列指南”描述resample()
为:“基于时间的分组依据,然后对每个分组采用归约方法”。因此,在groupby()
技术上,使用应.resample()
与在具有单个索引的DataFrame上使用相同的操作。
该段落指向有关重新采样的食谱部分,以获取更高级的示例,其中“ 使用MultiIndex分组 ”条目与此问题高度相关。希望能有所帮助。