Pandas 按名称将几组列融为多个目标列
Pandas Melt several groups of columns into multiple target columns by name
我想将数据框的几组列融合到多个目标列中。类似于问题 and pandas dataframe reshaping/stacking of multiple value variables into seperate columns。但是我需要通过列名而不是索引位置明确地执行此操作。
import pandas as pd
df = pd.DataFrame([('a','b','c',1,2,3,'aa','bb','cc'), ('d', 'e', 'f', 4, 5, 6, 'dd', 'ee', 'ff')],
columns=['a_1', 'a_2', 'a_3','b_1', 'b_2', 'b_3','c_1', 'c_2', 'c_3'])
df
原始数据框:
id a_1 a_2 a_3 b_1 b_2 b_3 c_1 c_2 c_3
0 101 a b c 1 2 3 aa bb cc
1 102 d e f 4 5 6 dd ee ff
目标数据框
id a b c
0 101 a 1 aa
1 101 b 2 bb
2 101 c 3 cc
3 102 d 4 dd
4 102 e 5 ee
5 102 f 6 ff
非常感谢有关此方法的建议。
您可以根据列模式将列名转换为多索引,然后根据您需要的结果在特定级别堆叠:
import pandas as pd
df.set_index('id', inplace=True)
df.columns = pd.MultiIndex.from_tuples(tuple(df.columns.str.split("_")))
df.stack(level = 1).reset_index(level = 1, drop = True).reset_index()
# id a b c
#101 a 1 aa
#101 b 2 bb
#101 c 3 cc
#102 d 4 dd
#102 e 5 ee
#102 f 6 ff
cols = df.columns.difference(['id'])
pd.lreshape(df, cols.groupby(cols.str.split('_').str[0])).sort_values('id')
Out:
id a c b
0 101 a aa 1
2 101 b bb 2
4 101 c cc 3
1 102 d dd 4
3 102 e ee 5
5 102 f ff 6
有一种更有效的方法可以解决这类涉及熔化多组不同色谱柱的问题。 pd.wide_to_long
专为这些确切情况而构建。
pd.wide_to_long(df, stubnames=['a', 'b', 'c'], i='id', j='dropme', sep='_')\
.reset_index()\
.drop('dropme', axis=1)\
.sort_values('id')
id a b c
0 101 a 1 aa
2 101 b 2 bb
4 101 c 3 cc
1 102 d 4 dd
3 102 e 5 ee
5 102 f 6 ff
一个选项是pivot_longer from pyjanitor,它抽象了过程,并且高效:
# pip install janitor
import janitor
df.pivot_longer(
index = None,
names_to = '.value',
names_pattern = '([a-z]+)_*')
a b c
0 a 1 aa
1 d 4 dd
2 b 2 bb
3 e 5 ee
4 c 3 cc
5 f 6 ff
此特定重塑的想法是,正则表达式中与 .value
配对的任何组都保留为列 header。
我想将数据框的几组列融合到多个目标列中。类似于问题
import pandas as pd
df = pd.DataFrame([('a','b','c',1,2,3,'aa','bb','cc'), ('d', 'e', 'f', 4, 5, 6, 'dd', 'ee', 'ff')],
columns=['a_1', 'a_2', 'a_3','b_1', 'b_2', 'b_3','c_1', 'c_2', 'c_3'])
df
原始数据框:
id a_1 a_2 a_3 b_1 b_2 b_3 c_1 c_2 c_3
0 101 a b c 1 2 3 aa bb cc
1 102 d e f 4 5 6 dd ee ff
目标数据框
id a b c
0 101 a 1 aa
1 101 b 2 bb
2 101 c 3 cc
3 102 d 4 dd
4 102 e 5 ee
5 102 f 6 ff
非常感谢有关此方法的建议。
您可以根据列模式将列名转换为多索引,然后根据您需要的结果在特定级别堆叠:
import pandas as pd
df.set_index('id', inplace=True)
df.columns = pd.MultiIndex.from_tuples(tuple(df.columns.str.split("_")))
df.stack(level = 1).reset_index(level = 1, drop = True).reset_index()
# id a b c
#101 a 1 aa
#101 b 2 bb
#101 c 3 cc
#102 d 4 dd
#102 e 5 ee
#102 f 6 ff
cols = df.columns.difference(['id'])
pd.lreshape(df, cols.groupby(cols.str.split('_').str[0])).sort_values('id')
Out:
id a c b
0 101 a aa 1
2 101 b bb 2
4 101 c cc 3
1 102 d dd 4
3 102 e ee 5
5 102 f ff 6
有一种更有效的方法可以解决这类涉及熔化多组不同色谱柱的问题。 pd.wide_to_long
专为这些确切情况而构建。
pd.wide_to_long(df, stubnames=['a', 'b', 'c'], i='id', j='dropme', sep='_')\
.reset_index()\
.drop('dropme', axis=1)\
.sort_values('id')
id a b c
0 101 a 1 aa
2 101 b 2 bb
4 101 c 3 cc
1 102 d 4 dd
3 102 e 5 ee
5 102 f 6 ff
一个选项是pivot_longer from pyjanitor,它抽象了过程,并且高效:
# pip install janitor
import janitor
df.pivot_longer(
index = None,
names_to = '.value',
names_pattern = '([a-z]+)_*')
a b c
0 a 1 aa
1 d 4 dd
2 b 2 bb
3 e 5 ee
4 c 3 cc
5 f 6 ff
此特定重塑的想法是,正则表达式中与 .value
配对的任何组都保留为列 header。