取消堆叠具有重复项的多索引
Posted
技术标签:
【中文标题】取消堆叠具有重复项的多索引【英文标题】:Unstacking a multi-index with duplicates 【发布时间】:2020-09-22 06:32:42 【问题描述】:我有一个看起来像这样的数据框
Date ID Value
Mar-20 A 100
Mar-20 B 200
Mar-20 C 300
Apr-20 A 101
Apr-20 B 201
Apr-20 C 301
我正在尝试重新塑造它,使其看起来像这样
Value
ID A B c
Date
Mar-20 100 200 300
Apr-20 101 201 301
我从尝试开始
df = df.set_index(["Date", "ID"])
但是将这个 let 取消堆叠到以下值错误:“索引包含重复的条目,无法重塑” 所以我在 SO 上找到了这个建议,这让我可以 unstack
df = df.set_index(["Date", "ID"].append = True)
但是当我通过“ID”(即 df = df.unstack("ID") 取消堆叠时,我的最终数据框看起来像这样
Value
Date ID A B C
Mar-20 A 100 NaN NaN
Mar-20 B NaN 200 NaN
Mar-20 C NaN NaN 300
Apr-20 A 101 NaN NaN
Apr-20 B NaN 201 NaN
Apr-20 C NaN NaN 301
如何压缩它以获得我想要的输出?
非常感谢
【问题讨论】:
@YOBEN_S - 是的,你支持 75% 正确,不幸的是,这个日期时间有点复杂。 @jezrael df.pivot(*df.columns)? @YOBEN_S - 好点,添加到答案中。 @jezrael 将重新打开呵呵 【参考方案1】:将DataFrame.unstack
用于预期输出(索引顺序已更改):
df = df.set_index(["Date", "ID"]).unstack()
print (df)
Value
ID A B C
Date
Apr-20 101 201 301
Mar-20 100 200 300
为了正确的顺序可以添加to_datetime
:
df['Date'] = pd.to_datetime(df['Date'], format='%b-%y')
df = df.set_index(["Date", "ID"]).unstack()
print (df)
Value
ID A B C
Date
2020-03-01 100 200 300
2020-04-01 101 201 301
如果需要正确顺序的原始格式:
df['Date'] = pd.to_datetime(df['Date'], format='%b-%y')
df = df.set_index(["Date", "ID"]).unstack().rename(lambda x: x.strftime('%b-%y'))
print (df)
Value
ID A B C
Date
Mar-20 100 200 300
Apr-20 101 201 301
如果只有 3 列可以使用DataFrame.pivot
,但如果更多列失败,所以如果一般数据不要使用它:
df['Date'] = pd.to_datetime(df['Date'], format='%b-%y')
df = df.pivot(*df.columns).rename(lambda x: x.strftime('%b-%y'))
print (df)
ID A B C
Date
Mar-20 100 200 300
Apr-20 101 201 301
如果输入数据中有任何列并且只需要旋转大约 3 列,则最好使用:
df['Date'] = pd.to_datetime(df['Date'], format='%b-%y')
df = df.pivot('Date','ID','Value').rename(lambda x: x.strftime('%b-%y'))
print (df)
ID A B C
Date
Mar-20 100 200 300
Apr-20 101 201 301
编辑:如果出现错误:
索引包含重复条目,无法重新整形
表示每对有重复的Date, ID
,所以必须使用聚合函数,如DataFrame.pivot_table
中的sum
、mean
:
print (df)
Date ID Value
0 Mar-20 A 100 <- same Date, ID
1 Mar-20 A 500 <- same Date, ID
2 Mar-20 B 200
3 Mar-20 C 300
4 Apr-20 A 101
5 Apr-20 B 201
6 Apr-20 C 301
df['Date'] = pd.to_datetime(df['Date'], format='%b-%y')
df = df.pivot_table(index='Date',
columns='ID',
values='Value',
aggfunc='sum').rename(lambda x: x.strftime('%b-%y'))
print (df)
ID A B C
Date
Mar-20 600 200 300 < aggregate sum 100+500=600
Apr-20 101 201 301
如果需要在MultiIndex
中使用列Value
:
df['Date'] = pd.to_datetime(df['Date'], format='%b-%y')
df = df.pivot_table(index='Date',
columns='ID',
values=['Value'],
aggfunc='sum').rename(lambda x: x.strftime('%b-%y'))
print (df)
Value
ID A B C
Date
Mar-20 600 200 300
Apr-20 101 201 301
如果需要避免排序更好的解决方案,谢谢@anky:
df = df.groupby(["Date", "ID"],sort=False)['Value'].sum().unstack()
print (df)
ID A B C
Date
Mar-20 600 200 300
Apr-20 101 201 301
【讨论】:
非常感谢您回到我身边。当我尝试第一个版本时,我收到“索引包含重复条目,无法重新整形”的值错误。当我将 append = True 添加到 set_index 时,我会得到不同版本的索引的负载(每个 ID 1 个) @harrison10001 - 检查最后一段以获得解决方案。 非常感谢。我会试一试 @anky - 谢谢。以上是关于取消堆叠具有重复项的多索引的主要内容,如果未能解决你的问题,请参考以下文章