看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
pandas 对数据进行排序时,常规的 sort_values() 方法可以满足大部分需求。在一些复杂的场景下,sort_values() 无法实现,这时我们就需要构建一个虚拟的列再用 sort_values() 进行排序。本例,就是这样的一个应该场景。
我们先看一下需求中的数据:
import pandas as pd
df = pd.DataFrame({'a': [3, 1, 4, 5, 0, 2],
'b': [4, '无', 1, 6, '无', 8]
})
df
'''
a b
0 3 4
1 1 无
2 4 1
3 5 6
4 0 无
5 2 8
'''
在这两列数据中,我们要按 a 值的大小排序,但要考虑 b 列,b 列的例如果是「无」,则需要将这行数据排在最后。
这个问题无法直接用 sort_values() 解决,因为 sort_values() 中给出两个列,会先按第一列排序,第一列中相同的值再按第二列排序,显然这无法实现我们要的效果。
我们可以构建一个虚拟的列,将 a 对应 b 列「无」的值替换为一个无限大的值,这样我们对这个虚拟列排序时它们就会在最后了。
首先,使用 mask() 圈选出为「无」的值:
df.a.mask(df.b=='无')
'''
0 3.0
1 NaN
2 4.0
3 5.0
4 NaN
5 2.0
Name: a, dtype: float64
'''
将圈选出的值替换为无穷大,float('inf')
代表无穷大的数。
df.a.mask(df.b=='无', float('inf'))
'''
0 3.0
1 inf
2 4.0
3 5.0
4 inf
5 2.0
Name: a, dtype: float64
'''
再对这个虚拟列使用 sort_values() 升序排列,并得到这个虚拟列。
order = df.a.mask(df.b=='无', float('inf')).sort_values()
order
'''
5 2.0
0 3.0
2 4.0
3 5.0
1 inf
4 inf
Name: a, dtype: float64
'''
得到的虚拟列 order 我们将其索引传入 reindex(),会按照此索引顺序重新排列 DataFrame 的顺序:
df.reindex(order.index)
'''
a b
5 2 8
0 3 4
2 4 1
3 5 6
1 1 无
4 0 无
'''
我们看到,这样就实现了我们想要的结果。
(完)
更新时间:Aug. 18, 2024, 4 p.m. 标签:pandas python 排序