重新采样 MultiIndexed Pandas DataFrame 并将不同的函数应用于列
Posted
技术标签:
【中文标题】重新采样 MultiIndexed Pandas DataFrame 并将不同的函数应用于列【英文标题】:Resample a MultiIndexed Pandas DataFrame and apply different functions to columns 【发布时间】:2017-09-30 23:20:48 【问题描述】:如果您没有 MultiIndexed 列,您可以执行 df.resample(freq).agg(some_dict)
其中 some_dict 的形式为 column_name: function
以便对每列应用不同的功能(参见下面的演示或参见 this question 或docs)。
当我有 MultiIndexed 列时,我也想这样做,但 Pandas 正在我的列和字典之间做乘积。
这里有一些虚拟数据可供使用:
In [1]:
import pandas as pd
import numpy as np
cols = pd.MultiIndex.from_tuples([('A', 'one'), ('A', 'two'),
('B', 'one'), ('B', 'two')])
ind = pd.DatetimeIndex(start='2017-01-01', freq='15Min', periods=20)
df = pd.DataFrame(np.random.randn(20,4), index=ind, columns=cols)
print(df.head())
Out[1]:
A B
one two one two
2017-01-01 00:00:00 -0.627329 0.756533 2.149236 -1.204808
2017-01-01 00:15:00 1.493381 1.320806 -1.692557 1.225271
2017-01-01 00:30:00 -0.572762 1.365679 -1.993464 1.118474
2017-01-01 00:45:00 -1.785283 -1.625370 -0.437199 0.776267
2017-01-01 01:00:00 -0.220307 1.308388 2.981333 -0.569586
现在,让我们创建一个聚合字典,将列映射到特定函数:
In [2]:
agg_dict = col:(np.sum if col[1] == 'one' else np.mean) for col in df.columns
agg_dict
Out[2]:
('A', 'one'): <function numpy.core.fromnumeric.sum>,
('A', 'two'): <function numpy.core.fromnumeric.mean>,
('B', 'one'): <function numpy.core.fromnumeric.sum>,
('B', 'two'): <function numpy.core.fromnumeric.mean>
在这里它不起作用,它实际上是在我的实际列和 agg_dict 之间进行乘积。我期望(5,4)
的形状,但我得到(5,16)
(dict 中有4 个条目,df 中有4 列):
In [3]: df.resample('H').agg(agg_dict).shape
Out[3]: (5,16)
In [4]: print(df.resample('H').agg(agg_dict).columns.tolist())
Out[4]: [('A', 'one', 'A', 'one'), ('A', 'one', 'A', 'two'), ('A', 'one', 'B', 'one'), ('A', 'one', 'B', 'two'), ('A', 'two', 'A', 'one'), ('A', 'two', 'A', 'two'), ('A', 'two', 'B', 'one'), ('A', 'two', 'B', 'two'), ('B', 'one', 'A', 'one'), ('B', 'one', 'A', 'two'), ('B', 'one', 'B', 'one'), ('B', 'one', 'B', 'two'), ('B', 'two', 'A', 'one'), ('B', 'two', 'A', 'two'), ('B', 'two', 'B', 'one'), ('B', 'two', 'B', 'two')]
我怎样才能获得与非 MultiIndexed 情况类似的行为,即在此处以 (5,4)
DataFrame 结束?
我可以使用非 MultiIndexed DataFrame 验证它是否有效。
In [5]:
df2 = df.copy()
# Flatten columns
df2.columns = ['_'.join(x) for x in df.columns]
# Create similar agg_dict
agg_dict2 = col:(np.sum if 'one' in col else np.mean) for col in df2.columns
print(df2.resample('H').agg(agg_dict2))
Out[5]:
A_one A_two B_one B_two
2017-01-01 00:00:00 -1.491994 0.454412 -1.973983 0.478801
2017-01-01 01:00:00 -0.931024 0.465611 4.837972 -0.118674
2017-01-01 02:00:00 2.015399 0.203814 1.539722 -0.296053
2017-01-01 03:00:00 -0.569376 -0.382343 -2.244470 -0.038828
2017-01-01 04:00:00 -0.747308 -0.212246 2.025314 0.713344
【问题讨论】:
【参考方案1】:我刚刚想出了一个想法,可以使用 apply
和 lambda
In [1]:
df.resample('H').apply(lambda x: agg_dict[x.name](x))
Out[1]:
A B
one two one two
2017-01-01 00:00:00 -2.211489 0.538068 1.379451 -0.619921
2017-01-01 01:00:00 1.524752 -0.195767 1.157592 0.137513
2017-01-01 02:00:00 -1.225071 0.020599 -1.372751 -0.245233
2017-01-01 03:00:00 2.922656 0.032864 3.118994 0.315109
2017-01-01 04:00:00 -1.438694 1.025585 1.915400 -0.536389
x.name
返回例如('A', 'one')
,所以我用它来选择字典中的函数,并将x
传递给它。
【讨论】:
如果 Pandas 有内置方法,我会全力以赴! 你有没有偶然发现一个内置的 Pandas 方法来做到这一点??以上是关于重新采样 MultiIndexed Pandas DataFrame 并将不同的函数应用于列的主要内容,如果未能解决你的问题,请参考以下文章
是否有 Pandas 解决方案——例如:使用 numba 或 Cython——使用索引、MultiIndexed DataFrame 来“转换”/“应用”?