pandas - 取消堆叠具有重复项的多索引
问题描述
我有一个看起来像这样的数据框
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"])
但是将其拆分为以下值错误:“索引包含重复的条目,无法重塑”所以我在 SO 上找到了这个建议,这让我可以拆分
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
如何压缩它以获得我想要的输出?
非常感谢
解决方案
用于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
必要使用聚合函数,sum
例如:mean
DataFrame.pivot_table
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
如果需要使用Value
列MultiIndex
:
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
推荐阅读
- ruby-on-rails - 如何在 postgres 的 updated_at 列中插入旧时间戳?
- angular - HTTP 查询参数
- javascript - 如何在 vue rollup 库中使用公共图片
- laravel - 如何将“wherePivot”应用于集合数据而不是关系本身?
- bash - 使用 shellscript 在多个文件中用新的随机密码替换旧密码
- csv - 将大型 .csv 文件导入 Google 表格时出现问题
- asp.net-web-api - Web API 项目无法在 Visual Studio 2019 中加载 - 错误:“方法或操作未实现”
- angular - 在angular8中“构建”后图像未加载
- scala - 在 Akka 中实现一个计时器
- android - 如何在Android中等待数据库数据而不阻塞数据库线程