看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
本需求有两部分组成。一是将指定的两行其值相加合并为一行,放在指定位置,另外一部分是对指定行调整顺序,放在首行和末行,最后返回一个调整过的数据。pandas 比较擅长对数据做细节的调整。
数据如下:
'''
x y z
Z 1 3
l 2 4
A 3 5
f 4 6
B 5 7
O 6 8
'''
需求:
先读取数据:
import pandas as pd
df = pd.read_clipboard()
df
# ...
总体思路为,先将 A、B 两行合并后的数据替换给 A 行,然后通过选择排队 B 行,达到删除 B 行目的。
接着,将 x 设置为索引,通过 reindex()
重新指定索引顺序的方法将指定的两行排到首行和末行。
在构造新的索引顺序列表时,可以将这两行先放在首尾列表,中间放置剩余的行标识。
先定义两个列表,一个是需要合并的行值列表,另一个是需要排序的行值列表。用 mask() 筛选出 A 行,用 A、B 值所在两行加和计算进行替换,替换前将加和后的 AB 值替换为 C:
for_merge = ['A', 'B'] # 需要合并的行值
for_order = ['f', 'l'] # 需要排序的行值
# 选择指定列
df[df.x.isin(for_merge)]
'''
x y z
2 A 3 5
4 B 5 7
'''
# 加和
df[df.x.isin(for_merge)].sum()
'''
x AB
y 8
z 12
dtype: object
'''
# 替换 x 的值为 C
c = (
df[df.x.isin(for_merge)]
.sum()
.replace({'AB': 'C'})
)
c
'''
x C
y 8
z 12
dtype: object
'''
c 为要替换的内容,用 mask() 替换 A 行内容:
df.mask(df.x=='A', c, axis=1)
'''
x y z
0 Z 1 3
1 l 2 4
2 C 8 12
3 f 4 6
4 B 5 7
5 O 6 8
'''
通过筛选删除 B 行:
(
df.mask(df.x=='A', c, axis=1)
.loc[lambda d: ~d.x.isin(for_merge)]
)
'''
x y z
0 Z 1 3
1 l 2 4
2 C 8 12
3 f 4 6
5 O 6 8
'''
接下来操作行的顺序,由于要利用索引的 reindex()
排序功能,将索引设置为 x 列,排序完后再重置回来。
构造新索引顺序列表时,将 f 和 l 先置于列表头尾,中间排除用于排序的两行,将这个列表用星号解包置于列表中间。
上边的这个操作过程是针对 DataFrame 整体的,因此用 pipe() 来调用:
(
df.mask(df.x=='A', c, axis=1)
.loc[lambda d: ~d.x.isin(for_merge)]
.set_index('x')
.pipe(lambda d: d.reindex(['f', *d[~d.index.isin(for_order)].index, 'l']))
.reset_index()
)
以上就得到了最终结果。完整代码如下:
for_merge = ['A', 'B'] # 需要合并的行值
for_order = ['f', 'l'] # 需要排序的行值
(
df.mask(df.x=='A', df[df.x.isin(for_merge)].sum().replace({'AB': 'C'}), axis=1)
.loc[lambda d: ~d.x.isin(for_merge)]
.set_index('x')
.pipe(lambda d: d.reindex(['f', *d[~d.index.isin(for_order)].index, 'l']))
.reset_index()
)
'''
x y z
0 f 4 6
1 Z 1 3
2 C 8 12
3 O 6 8
4 l 2 4
'''
这样就完成了需求。
(完)
更新时间:2024-08-18 15:56:22 标签:pandas python 合并 排顺