看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
本例是日常办公中数据整理的一个需求, 在整理数据中将所有的数据整理在行上, 但最后在统计的时候需要将不同的组分别整理在列上。 pandas 提供的数据变形方法可以灵活地将数据的格式进行转化以满足办公中对数据整理的需求。
我们先来看一下原始数据, 以及期望整理的目标数据形式:
# 原数据
'''
Col1 Col2
Part A
1 name
2 namee
3 nameee
Part B
1 value
2 valuee
3 valueee
4 valueeee
Part C
1 key
2 keyy
'''
# 转为
'''
A B C
1 name value key
2 namee valuee keyy
3 nameee valueee NaN
4 NaN valueeee NaN
'''
import pandas as pd
# 复制数据读取到 DataFrame
df = pd.read_clipboard()
df
# ...
在原始数据中我们看到有两列,一列是分组及其分组的序号, 另一列是具体的值。 最后在数据整理的时候期望一列为一个分组的值,同时列名是这个分组的列名, 我们索引是原数据的序号。
从数据原数据和目标数据的形式上分析,这是一个数据透视过程,不过在透视之前要将 Part 行的组补充上。我们可以增加一个辅助列,这个列的逻辑是以 Col2 列基础,将对应行 C Col1 的值不为 Part 的进行向前填充,填充为分组值。
有了分组名,我们就过滤掉 Part 标识行,直接进行透视操作。
用 where 判断 Col1 列不为 Part 的为缺失值,对 Col2 进行向前填充:
df.Col2.where(df.Col1 == 'Part').ffill()
'''
0 A
1 A
2 A
3 A
4 B
5 B
6 B
7 B
8 B
9 C
10 C
11 C
Name: Col2, dtype: object
'''
将这个辅助列命名为 Part,增加到 DataFrame 中:
(
df.assign(Part=df.Col2.where(df.Col1 == 'Part').ffill())
)
'''
Col1 Col2 Part
0 Part A A
1 1 name A
2 2 namee A
3 3 nameee A
4 Part B B
5 1 value B
6 2 valuee B
7 3 valueee B
8 4 valueeee B
9 Part C C
10 1 key C
11 2 keyy C
'''
过滤掉 Part 行,我们这里使用了 Col2 和 Part 列值不相同,当然可以直接判断 Col1 列的值不为 Part,这里主要是为了演示更多功能。
(
df.assign(Part=df.Col2.where(df.Col1 == 'Part').ffill())
.loc[lambda d: ~(d.Part == d.Col2)]
)
'''
Col1 Col2 Part
1 1 name A
2 2 namee A
3 3 nameee A
5 1 value B
6 2 valuee B
7 3 valueee B
8 4 valueeee B
10 1 key C
11 2 keyy C
'''
用 pipe 调用 pd.pivot() 透视函数,对整个 DataFrame 进行透视,关键字参数是传给 pd.pivot() 函数的参数:
(
df.assign(Part=df.Col2.where(df.Col1 == 'Part').ffill())
.loc[lambda d: ~(d.Part == d.Col2)]
.pipe(pd.pivot, values='Col2', columns='Part', index='Col1')
)
'''
Part A B C
Col1
1 name value key
2 namee valuee keyy
3 nameee valueee NaN
4 NaN valueeee NaN
'''
最终得到了期望的数据,这样就完成了需求。
(完)
更新时间:2024-08-18 15:55:59 标签:pandas python 分组