【发布时间】:2022-11-10 16:25:32
【问题描述】:
目前,我有一个看起来像这样的数据框:
| abc | def | ghi | abc | def | ghi |
|---|---|---|---|---|---|
| 2 | 4 | 78 | 56 | 7 | 45 |
有没有办法组合具有相同名称的列并为每组值创建一个新行?例子:
| abc | def | ghi |
|---|---|---|
| 2 | 4 | 78 |
| 56 | 7 | 45 |
【问题讨论】:
目前,我有一个看起来像这样的数据框:
| abc | def | ghi | abc | def | ghi |
|---|---|---|---|---|---|
| 2 | 4 | 78 | 56 | 7 | 45 |
有没有办法组合具有相同名称的列并为每组值创建一个新行?例子:
| abc | def | ghi |
|---|---|---|
| 2 | 4 | 78 |
| 56 | 7 | 45 |
【问题讨论】:
您可以使用.groupby(level=0, axis='columns') 分配累积计数,然后基于该计数执行转换。
import pandas as pd
new_cols = pd.MultiIndex.from_arrays([df.columns, df.groupby(level=0, axis=1).cumcount()])
out = df.set_axis(new_cols, axis=1).stack().reset_index(level=0, drop=True)
print(out)
abc def ghi
0 2 4 78
1 56 7 45
【讨论】:
您可以在 groupby.cumcount 和 stack 的帮助下设置 MultiIndex:
(df
.set_axis(pd.MultiIndex
.from_arrays([df.columns,
df.groupby(level=0, axis=1)
.cumcount()]), axis=1)
.stack()
.droplevel(0)
)
输出:
abc def ghi
0 2 4 78
1 56 7 45
【讨论】:
只是用melt 替代其他答案:
out = (df.melt(var_name='col', value_name='val')
.assign(idx=lambda x: x.groupby('col').cumcount())
.pivot('idx', 'col', 'val').rename_axis(index=None, columns=None))
print(out)
# Output
abc def ghi
0 2 4 78
1 56 7 45
【讨论】:
一种选择是使用来自pyjanitor 的pivot_longer:
# pip install pyjanitor
import pandas as pd
import janitor
df.pivot_longer(names_to = '.value', names_pattern = '(.+)')
abc def ghi
0 2 4 78
1 56 7 45
在上述解决方案中,.value 确定列标签的哪些部分保留为标题 - 标签由names_pattern 中正则表达式中的组确定。
另一种选择是将新列的名称传递给names_to,同时将匹配的正则表达式列表传递给names_pattern:
df.pivot_longer(names_to = ['abc', 'def', 'ghi'],
names_pattern = ['abc', 'def', 'ghi'])
abc def ghi
0 2 4 78
1 56 7 45
【讨论】:
df1.T.rename_axis('col1',axis=1).assign(group=lambda dd:(dd.index=='abc').cumsum())
.pivot_table(index='group',columns='col1',values=0)
col1 abc def ghi
1 2 4 78
2 56 7 45
【讨论】: