我有一个与 Pandas 相关的问题。我的数据框看起来像这样:
id val1 val2
0 1 0 1
1 1 1 0
2 1 0 0
3 2 1 1
4 2 1 1
5 2 1 0
6 3 0 0
7 3 0 1
8 3 1 1
9 4 1 0
10 4 0 1
11 4 0 0
我想把它改成这样:
a b c
id a0 a1 b0 b1 c0 c1
1 0 1 1 0 0 0
2 1 1 1 1 1 0
3 0 0 1 1 1 1
4 1 0 0 1 0 0
我想到了添加一个由 a、b 和 c 循环枚举的 sub_id 列,然后对帧进行 unstack。有更简单/更智能的解决方案吗?
非常感谢!
蒂姆
最佳答案
如果可能的话,使用 GroupBy.cumcount
代替 abc
数字对于计数器,通过 DataFrame.set_index
创建 MultiIndex
并通过 DataFrame.unstack
reshape 最后对第二级进行排序 DataFrame.swaplevel
:
g = df.groupby('id').cumcount()
df = df.set_index(['id', g]).unstack().sort_index(axis=1, level=1).swaplevel(0,1,axis=1)
print (df)
0 1 2
val1 val2 val1 val2 val1 val2
id
1 0 1 1 0 0 0
2 1 1 1 1 1 0
3 0 0 0 1 1 1
4 1 0 0 1 0 0
如果想要a,b,c
值可以从string.ascii_lowercase
和rename
列生成字典:
import string
d = dict(enumerate(string.ascii_lowercase))
df = df.rename(columns=d)
print (df)
a b c
val1 val2 val1 val2 val1 val2
id
1 0 1 1 0 0 0
2 1 1 1 1 1 0
3 0 0 0 1 1 1
4 1 0 0 1 0 0
重命名两个级别的解决方案是首先在set_index
之后按范围创建默认列名称:
g = df.groupby('id').cumcount()
df = df.set_index(['id', g])
df.columns = range(len(df.columns))
df = df.unstack().sort_index(axis=1, level=1).swaplevel(0,1,axis=1)
print (df)
0 1 2
0 1 0 1 0 1
id
1 0 1 1 0 0 0
2 1 1 1 1 1 0
3 0 0 0 1 1 1
4 1 0 0 1 0 0
最后在列表理解中设置新值:
import string
d = dict(enumerate(string.ascii_lowercase))
df.columns = pd.MultiIndex.from_tuples([(d[a], f'{d[a]}{b}') for a, b in df.columns])
print (df)
a b c
a0 a1 b0 b1 c0 c1
id
1 0 1 1 0 0 0
2 1 1 1 1 1 0
3 0 0 0 1 1 1
4 1 0 0 1 0 0
关于python - Pandas: reshape 数据框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60968943/