如何解决按 N 列块重塑 Pandas 数据框列
我有 1 个数据框,其中的列块需要重新调整为行。 我尝试使用 stack() 和 Melt() 但无法找到正确的方法。
这是我期望的示例:
data = {'id':['a1','a2','a3','a4'],'year':[20,20,19,18],'b_A': [1,2,3,4],'b_B': [5,6,7,8],'b_C': [9,10,11,12],'c_A': [13,14,15,16],'c_B': [17,18,20],'c_C': [21,22,23,24],'d_A': [25,26,27,28],'d_B': [29,30,31,32],'d_C': [33,34,35,36],}
df = pd.DataFrame(data)
id year b_A b_B b_C c_A c_B c_C d_A d_B d_C
0 a1 20 1 5 9 13 17 21 25 29 33
1 a2 20 2 6 10 14 18 22 26 30 34
2 a3 19 3 7 11 15 19 23 27 31 35
3 a4 18 4 8 12 16 20 24 28 32 36
预期结果应该是:
id year origin A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
感谢您的时间和帮助。
解决方法
您可以将 _
的非列名称转换为 DataFrame.set_index
的索引,然后将列按 Series.str.split
拆分并按 DataFrame.stack
进行整形:
df1 = df.set_index(['id','year'])
df1.columns = df1.columns.str.split('_',expand=True)
df1 = df1.stack(level=0).reset_index()
print (df1)
id year level_2 A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
如果还需要设置列 origin
可以使用 DataFrame.rename_axis
:
df1 = df.set_index(['id',expand=True)
df1 = df1.rename_axis(['origin',None],axis=1).stack(0).reset_index()
print (df1)
id year origin A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
或者将 wide_to_long
与 _
的值的更改顺序一起使用,例如 A_b
到 b_A
:
df.columns = [f'{"_".join(x[::-1])}' for x in df.columns.str.split('_')]
df1 = pd.wide_to_long(df,stubnames=['A','B','C'],i=['id','year'],j='origin',sep='_',suffix=r'\w+').reset_index()
print (df1)
id year origin A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
,
您也可以使用 pivot_longer 中的 pyjanitor 函数;目前您必须从 github:
安装最新的开发版本 # install latest dev version
# pip install git+https://github.com/ericmjl/pyjanitor.git
import janitor
df.pivot_longer(index=["id","year"],names_to=("origin",".value"),names_sep="_")
id year origin A B C
0 a1 20 b 1 5 9
1 a2 20 b 2 6 10
2 a3 19 b 3 7 11
3 a4 18 b 4 8 12
4 a1 20 c 13 17 21
5 a2 20 c 14 18 22
6 a3 19 c 15 19 23
7 a4 18 c 16 20 24
8 a1 20 d 25 29 33
9 a2 20 d 26 30 34
10 a3 19 d 27 31 35
11 a4 18 d 28 32 36
names_sep
值拆分列;与 .value
配对的拆分值保留为列标题,而其他值则集中在 origin
列下方。
如果你想要数据按出现的顺序,你可以使用sort_by_appearance
参数:
df.pivot_longer(
index=["id",names_sep="_",sort_by_appearance=True,)
id year origin A B C
0 a1 20 b 1 5 9
1 a1 20 c 13 17 21
2 a1 20 d 25 29 33
3 a2 20 b 2 6 10
4 a2 20 c 14 18 22
5 a2 20 d 26 30 34
6 a3 19 b 3 7 11
7 a3 19 c 15 19 23
8 a3 19 d 27 31 35
9 a4 18 b 4 8 12
10 a4 18 c 16 20 24
11 a4 18 d 28 32 36
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。