0%

怎么将值转换为列?

❓ 我有以下数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd

df = pd.DataFrame({
'A': [1, 3, 2, 1, 2],
'B': [2, 1, 3, 2, 3],
'C': [3, 2, 1, 3, 1],
})
print(df)
# A B C
# 0 1 2 3
# 1 3 1 2
# 2 2 3 1
# 3 1 2 3
# 4 2 3 1

此数据表示每一行的每个选项A,B和C的“排名”。例如,在第2行中,C是最好的,然后是A,然后是B。我想构造“倒置”数据帧,其中对于每一行,我在1、2和3位置有三列排名中的A,B和C现在是数据。因此,对于上面的示例,结果将是:

1
2
3
4
5
6
7
8
9
10
11
12
out = pd.DataFrame({
1: ['A', 'B', 'C', 'A', 'C'],
2: ['B', 'C', 'A', 'B', 'A'],
3: ['C', 'A', 'B', 'C', 'B'],
})
print(out)
# 1 2 3
# 0 A B C
# 1 B C A
# 2 C A B
# 3 A B C
# 4 C A B

理想情况下,df中的每一行都应具有三个不同的值1、2和3,但是在某些情况下可能会有重复的值(不需要考虑超出该范围的值)。如果可能的话,我想通过在相同位置“连接”选项名称并在缺少位置使用空字符串或NaN来解决此问题。例如,使用以下输入:

1
2
3
4
df_bad = pd.DataFrame({'A': [1], 'B': [2], 'C': [2]})
print(df_bad)
# A B C
# 0 1 2 2

理想情况下,我希望获得以下输出:

1
2
3
4
out_bad = pd.DataFrame({1: ['A'], 2: ['BC'], 3: ['']})
print(out_bad)
# 1 2 3
# 0 A BC

另外,我可以选择仅获取其中一个值而不是并置。我一直在浏览meltpivotpivot_table和其他函数,但无法弄清楚获得所需结果的方法。


✔️ 对于重复排名的情况(例如第二个示例),在最后一步使用pivotunstack的任何解决方案都会失败。 您需要pivot_tablecrosstab。 正如您已经找到了使用pivot_table的解决方案。 这是crosstab例子:

1
2
3
4
5
6
7
8
df2 = df_bad.stack().reset_index(1, name='cols')
pd.crosstab(index=df2.index, columns=df2.cols, values=df2.level_1,
aggfunc=''.join).fillna('')

Out[171]:
cols 1 2
row_0
0 A BC

使用stackpivot

1
2
3
4
5
6
7
8
9
df.stack().reset_index(1, name='cols').pivot(columns='cols', values='level_1')

Out[131]:
cols 1 2 3
0 A B C
1 B C A
2 C A B
3 A B C
4 C A B