看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
在数据形式的展示上,为了方便观察,我们有时需要对分组数据展示一个行上,这样可以以分组的视角去看数据,这个过程没有聚合计算。在本例中,我们就可实现一个这样相对实用却有点复杂的 pandas 数据格式转换案例。
我们的源数据如下:
import pandas as pd
from io import StringIO
data = '''
id,D,M,U
1,x1,x2,x3
1,y1,,y3
1,z1,z2,z3
2,a1,a2,a3
2,b1,b2,
3,c1,,
4,,d2,d3
'''
df = pd.read_csv(StringIO(data))
'''
id D M U
0 1 x1 x2 x3
1 1 y1 NaN y3
2 1 z1 z2 z3
3 2 a1 a2 a3
4 2 b1 b2 NaN
5 3 c1 NaN NaN
6 4 NaN d2 d3
'''
这是一个有点稀疏的数据,它的 id 列是一个分类数据,其他的都是文本。
文本数据存在一定的规律,后缀的值刚好是 DMU 三个字母的顺序号。
需求是想最终得到如下的数据:
# 目标数据结果
'''
D1 M1 U1 D2 M2 U2 D3 M3 U3
id
1 x1 x2 x3 y1 NaN y3 z1 z2 z3
2 a1 a2 a3 b1 b2 NaN NaN NaN NaN
3 c1 NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN d2 d3 NaN NaN NaN NaN NaN NaN
'''
即按 id 分组,并将组内的多行数据转为一个宽行,DMU 有三列,组内最多有三行,那么想得到 9 一数据。
每个列由 DMU 加后缀序号组成,后缀对应值为在组内行顺序,数据值为此规则的对应值。
接下来,我们分析完成这个需求。
将数据按 id 分组,所得的每组 DataFrame 转为一个 Series,就得到了一个堆叠形式的数据。再将这个堆叠的数据解答堆叠就基本得到了我们要的数据。
最后按要求重新设置列名即可。
先将数据的索引设置为 id,方便后续操作:
df = df.set_index('id')
df
'''
D M U
id
1 x1 x2 x3
1 y1 NaN y3
1 z1 z2 z3
2 a1 a2 a3
2 b1 b2 NaN
3 c1 NaN NaN
4 NaN d2 d3
'''
按索引分组,对分组后的每个子 DataFrame 利用 NumPy 的 array 方法展平,即将二维结构转为一个一维结构,再读入 Series:
(
df.groupby(level=0)
.apply(lambda x: pd.Series(x.to_numpy().flatten()))
)
'''
id
1 0 x1
1 x2
2 x3
3 y1
4 NaN
5 y3
6 z1
7 z2
8 z3
2 0 a1
1 a2
2 a3
3 b1
4 b2
5 NaN
3 0 c1
1 NaN
2 NaN
4 0 NaN
1 d2
2 d3
dtype: object
'''
得到了一个堆叠数据,接下来们解除堆叠便可得到想要的数据。
(
df.groupby(level=0)
.apply(lambda x: pd.Series(x.to_numpy().flatten()))
.unstack()
)
'''
0 1 2 3 4 5 6 7 8
id
1 x1 x2 x3 y1 NaN y3 z1 z2 z3
2 a1 a2 a3 b1 b2 NaN NaN NaN NaN
3 c1 NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN d2 d3 NaN NaN NaN NaN NaN NaN
'''
最后我们构造并修改列的索引标签值:
(
df.groupby(level=0)
.apply(lambda x: pd.Series(x.to_numpy().flatten()))
.unstack()
.set_axis([f'{c}{i}' for i in range(1, 4) for c in df.columns],
axis=1
)
)
'''
D1 M1 U1 D2 M2 U2 D3 M3 U3
id
1 x1 x2 x3 y1 NaN y3 z1 z2 z3
2 a1 a2 a3 b1 b2 NaN NaN NaN NaN
3 c1 NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN d2 d3 NaN NaN NaN NaN NaN NaN
'''
这样就得到了最终需要的数据。
(完)
更新时间:Aug. 18, 2024, 4:01 p.m. 标签:pandas python 分组 宽表