[英]Pivot a two-column dataframe
题
我的数据框untidy
attribute value
0 age 49
1 sex M
2 height 176
3 age 27
4 sex F
5 height 172
'attribute'
列中的值会定期重复。 所需的输出tidy
age sex height
0 49 M 176
1 27 F 172
(行和列的顺序或其他标签无关紧要,我可以自己清理。)
实例化代码:
untidy = pd.DataFrame([['age', 49],['sex', 'M'],['height', 176],['age', 27],['sex', 'F'],['height', 172]], columns=['attribute', 'value'])
tidy = pd.DataFrame([[49, 'M', 176], [27, 'F', 172]], columns=['age', 'sex', 'height'])
尝试次数
这看起来像一个简单的枢轴操作,但是我的初始方法引入了NaN
值:
>>> untidy.pivot(columns='attribute', values='value')
attribute age height sex
0 49 NaN NaN
1 NaN NaN M
2 NaN 176 NaN
3 27 NaN NaN
4 NaN NaN F
5 NaN 172 NaN
一些混乱的尝试来解决此问题:
>>> untidy.pivot(columns='attribute', values='value').apply(lambda c: c.dropna().reset_index(drop=True))
attribute age height sex
0 49 176 M
1 27 172 F
>>> untidy.set_index([untidy.index//untidy['attribute'].nunique(), 'attribute']).unstack('attribute')
value
attribute age height sex
0 49 176 M
1 27 172 F
惯用的方法是什么?
将pandas.pivot
与GroupBy.cumcount
一起使用以获取新的索引值,并使用rename_axis
移除列名称:
df = pd.pivot(index=untidy.groupby('attribute').cumcount(),
columns=untidy['attribute'],
values=untidy['value']).rename_axis(None, axis=1)
print (df)
age height sex
0 49 176 M
1 27 172 F
另一个解决方案:
df = (untidy.set_index([untidy.groupby('attribute').cumcount(), 'attribute'])['value']
.unstack()
.rename_axis(None, axis=1))
一种替代方法是首先使用累积年龄计数来引入新列:
untidy["index"] = (untidy["attribute"] == "age").cumsum() - 1
现在不整洁的样子
attribute value index
0 age 49 0
1 sex M 0
2 height 176 0
3 age 27 1
4 sex F 1
5 height 172 1
这样,您可以像这样基于属性和索引创建多索引数据框
tidy = untidy.set_index(["index", "attribute"]).unstack()
导致以下格式
value
attribute age height sex
index
0 49 176 M
1 27 172 F
唯一剩下的问题是,列现在是一个多索引,级别太多了。 您可以摆脱它,但首先将列作为索引转置,放下索引的级别并将其转回
tidy = tidy.T.reset_index(level=0).drop("level_0", axis=1).T
最终结果是您的数据框架整洁
attribute age height sex
index
0 49 176 M
1 27 172 F
您当然可以将第二步和第三步结合在一起。 我不确定这是否更惯用,但对我而言至少是更直观的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.