Python 使用agg()函数创建数据透视帧
假设我有一个数据透视框的形式Python 使用agg()函数创建数据透视帧,python,pandas,pivot,aggregate,resampling,Python,Pandas,Pivot,Aggregate,Resampling,假设我有一个数据透视框的形式 Value Qty Code Color Blue Green Red Blue Green Red Blue Green Red Date 2017-07-01 0.0 1.1 0.0 0.0 12.0 0.0 0 abc
Value Qty Code
Color Blue Green Red Blue Green Red Blue Green Red
Date
2017-07-01 0.0 1.1 0.0 0.0 12.0 0.0 0 abc 0
2017-07-03 2.3 1.3 0.0 3.0 1.0 0.0 cde abc 0
2017-07-06 0.0 0.0 1.4 0.0 0.0 1.0 0 0 cde
我对将日期重新采样为每周频率感兴趣。我想对主列的每个子列执行以下转换,Value:max,Qty:sum,Code=last。在正常的非多索引数据帧df中,可以通过agg()函数执行以下操作
df.resample('W').agg({"Value":"max", "Qty":"sum", "Code":"last"})
但是当我尝试使用数据透视框时,它不喜欢键。在多索引数据帧的情况下,如果不显式指定所有子列,我将如何执行此操作
预期产量为
Value Qty Code
Color Blue Green Red Blue Green Red Blue Green Red
Date
2017-07-02 0.0 1.1 0.0 0.0 12.0 0.0 0 abc 0
2017-07-09 2.3 1.3 1.4 3.0 1.0 1.0 0 0 cde
要生成上述起始数据帧,请使用以下代码
from collections import OrderedDict
import pandas as pd
table = OrderedDict((
("Date", ["2017-07-01", "2017-07-03", "2017-07-03", "2017-07-6"]),
('Color',['Green', 'Blue', 'Green', 'Red']),
('Value', [1.1, 2.3, 1.3, 1.4]),
('Qty', [12, 3, 1, 1]),
('Code', ['abc', 'cde', 'abc', 'cde'])
))
d = pd.DataFrame(table)
p = d.pivot(index='Date', columns='Color')
p.index = pd.to_datetime(p.index)
p.fillna(0, inplace=True)
编辑:添加所需的结果
编辑2:我还尝试创建一个字典来输入agg()函数,但是它有4个级别的列标题
dc = dict(zip(p.columns, map({'Value': 'max', 'Qty': 'sum', 'Code': 'last'}.get, [x[0] for x in p.columns])))
newp = p.resample('W').agg(dc)
我相信您需要
stack()
来避免多索引。在groupby
或resample
对象的agg
方法中似乎没有指定level=0
的方法,因此这是我唯一能找到它的方法(如果不准确,请告诉我):
堆栈将沿轴0将颜色带到索引
,重置索引以将多索引
转换为日期时间索引
,其余部分非常简单
编辑
这行吗
dic = {'Value': 'max', 'Qty': 'sum', 'Code': 'last'}
df = pd.DataFrame()
for i in p.columns.get_level_values(0).unique():
temp = p.xs(i, axis=1, level=0, drop_level=False).resample('W').agg(dic[i])
df = pd.concat([df, temp], axis=1)
df.columns=p.columns
df
Value Qty Code
Color Blue Green Red Blue Green Red Blue Green Red
Date
2017-07-02 0.0 1.1 0.0 0.0 12.0 0.0 0 abc 0
2017-07-09 2.3 1.3 1.4 3.0 1.0 1.0 0 0 cde
我不知道这种方法如何“防故障”,所以请小心。设置df.columns=p.columns
似乎很粗略,但保持多索引一直是主要的挑战。如果我在pd.concat()
中设置levels=p.columns.levels
(这似乎更安全),它会将索引展平为元组,元组也可以解压为多索引。我已经用几种不同的方法对此进行了测试,结果似乎不错。首先考虑将分层列组合起来,并按不同的列类型(值、数量和代码)运行每周聚合
要保留原始分层列,请在展平列级别之前保存列对象,然后在重采样过程后重新指定回列:
pvtcolumns = p.columns
# ...same code as above
out.columns = pvtcolumns
print(df)
# Value Qty Code
# Color Blue Green Red Blue Green Red Blue Green Red
# Date
# 2017-07-02 0.0 1.1 0.0 0.0 12.0 0.0 0 abc 0
# 2017-07-09 2.3 1.3 1.4 3.0 1.0 1.0 0 0 cde
您的预期输出是什么?谢谢您的尝试。我希望保留相同的列结构,但将索引重新采样到每周一次。本质上,p.resample('W').max()为值列提供了正确答案。p、 重采样('W')。sum()为Qty列提供了正确答案。代码列的p.resample('W').last()。我想我可以单独做所有这些,并将正确的列合并到一起,但我希望有一个更通用的方法。另一个选择是将列多重索引展平,并以这种方式执行计算。我试过几种不同的方法,但看起来并不干净。你介意分享一下你是如何展平多索引列的吗?我不熟悉多索引数据帧,我一直在寻找有趣的技术。:-)当然,请尝试以下操作-df.columns=[''.join(col.strip(),用于df.columns.values中的col]
。感谢安迪·海登的回答。我给出的示例起始数据帧(p)代表了我在多次操作后所得到的结果,例如cumsum,跨越x轴的代数操作。我看不出我怎么能轻易地解开它。是否可以从上面的p开始连接到上面的解决方案?
# COMBINE THE LIST OF MULTI-LEVEL COLUMN (LIST OF TUPLES)
p.columns = [i[0]+i[1] for i in p.columns]
p.columns = p.columns.get_level_values(0)
# HORIZONTAL MERGE
out = pd.concat([p.resample('W').max()[[c for c in p.columns if 'Value' in c]],
p.resample('W').sum()[[c for c in p.columns if 'Qty' in c]],
p.resample('W').last()[[c for c in p.columns if 'Code' in c]]], axis=1)
print(out)
# ValueBlue ValueGreen ValueRed QtyBlue QtyGreen QtyRed CodeBlue CodeGreen CodeRed
# Date
# 2017-07-02 0.0 1.1 0.0 0.0 12.0 0.0 0 abc 0
# 2017-07-09 2.3 1.3 1.4 3.0 1.0 1.0 0 0 cde
pvtcolumns = p.columns
# ...same code as above
out.columns = pvtcolumns
print(df)
# Value Qty Code
# Color Blue Green Red Blue Green Red Blue Green Red
# Date
# 2017-07-02 0.0 1.1 0.0 0.0 12.0 0.0 0 abc 0
# 2017-07-09 2.3 1.3 1.4 3.0 1.0 1.0 0 0 cde