unstack实例:DataFrame 去除一对多关系之行转列方法详解(附unstack()使用场景及代码)
stack()即“堆叠”,作用是将列旋转到行
unstack()即stack()的反操作,将行旋转到列
unstack(): Series对象的API,用于将Series的数据类型转DataFrame类型(因为DataFrame提供的数据操作API远远多于Series)。(Series视作一维,DataFrame视作高维数据,类比一维数组和高维度数组)
报错原因:用unstack操作的数据必须唯一标识
首先看可以行转列的数据形式:
转换前
代码:
# 将"姓名"和"科目"设置为索引, 然后取出"分数"这一列, 得到的对应的具有二级索引的Series对象
two_level_index_series = df.set_index(["姓名", "科目"])["分数"]
# 调用具有二级索引的Series的unstack, 会得到一个DataFrame
# 并会自动把一级索引变成DataFrame的索引, 二级索引变成DataFrame的列
new_df = two_level_index_series.unstack()
print(new_df)
"""
科目 数学 英语 语文
姓名
古明地觉 95 96 90
琪露诺 9 91 100
芙兰朵露 92 98 87
"""
# 是不是改回来了呢? 但是还有不完美的地方, 这个DataFrame的索引和列都有一个名字
# 索引的名字叫"姓名", 列的名字叫"科目", 因为原来Series的两个索引就叫"姓名"和"科目"
# 可以通过 rename_axis(index=, columns=) 来给坐标轴重命名
new_df = new_df.rename_axis(columns=None)
# 这里我们只给列重命名, 没有给索引重命名, 至于原因请往下看
new_df = new_df.reset_index()
print(new_df)
"""
姓名 数学 英语 语文
0 古明地觉 95 96 90
1 琪露诺 9 91 100
2 芙兰朵露 92 98 87
"""
# 大功告成, 如果index的名字变为空的话, 那么reset_index之后, 列名就会变成index
# 但如果原来的索引有名字, 那么reset_index之后, 列名就是原来的索引名
转换过后:
推荐阅读原博客:pandas行转列、列转行、以及一行生成多行
错误数据形式:
试图行转列的报错代码:
model_unstack_df=model1_df.set_index(['report_id','position'])['name'].unstack().add_prefix('position_').add_suffix('_name')
model_unstack_df.head()
分析:
这里的report_id=548947422542434000【红框】时,position对应有三个不同的name,索引包含重复的条目,unstack()就无法重新设置其形状;
而report_id=548947422542434001【篮框】时,position和name是一一对应的,可以行转列。