看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注: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  无
'''
我们看到,这样就实现了我们想要的结果。
(完)
更新时间:2024-08-18 16:00:45 标签:pandas python 排序