首页 > 解决方案 > 对包含表示 Pandas 中软件版本的字符串的列进行排序

问题描述

我有一个数据框,其中一列是带有软件名称和不同版本的字符串。尝试按此列排序时,排序不尊重版本控制。

要排序的列具有这种格式

>>> import pandas as pd
>>> df = pd.DataFrame({'versions': ['cd-2.8.10', 'cd-3.10.3', 'cd-3.3.1', 'cd-3.10.10', 'cd-3.12.0', 'ab-5.2.1', 'cd-3.1.3', 'cd-3.5.2', 'ab-3.0.2', 'cd-3.10.1', 'cd-3.20.1', 'cd-3.11.4']})
>>> df
      versions
0    cd-2.8.10
1    cd-3.10.3
2     cd-3.3.1
3   cd-3.10.10
4    cd-3.12.0
5     ab-5.2.1
6     cd-3.1.3
7     cd-3.5.2
8     ab-3.0.2
9    cd-3.10.1
10   cd-3.20.1
11   cd-3.11.4

sort_values()在破折号之前使用带有字符的字符串部分时,按字母顺序完美排序,但对于给定的软件,版本号排序错误,3.10.1因为小于3.3.13.10.10小于3.10.3

>>> df.sort_values('versions')
      versions
8     ab-3.0.2
5     ab-5.2.1
0    cd-2.8.10
6     cd-3.1.3
9    cd-3.10.1
3   cd-3.10.10
1    cd-3.10.3
11   cd-3.11.4
4    cd-3.12.0
10   cd-3.20.1
2     cd-3.3.1
7     cd-3.5.2

我想获得正确的版本排序

      versions
8     ab-3.0.2
5     ab-5.2.1
0    cd-2.8.10
6     cd-3.1.3
2     cd-3.3.1
7     cd-3.5.2
9    cd-3.10.1
1    cd-3.10.3
3   cd-3.10.10
11   cd-3.11.4
4    cd-3.12.0
10   cd-3.20.1

标签: pythonpandassorting

解决方案


这是一个复杂的问题,因为 pandas 不直接支持自然排序。值得庆幸的是,使用该natsort模块,这应该很容易并且还可以处理大多数版本格式。

from natsort import natsorted
df.iloc[natsorted(df.index, key=lambda x: df.loc[x, 'versions'])]

      versions
8     ab-3.0.2
5     ab-5.2.1
0    cd-2.8.10
6     cd-3.1.3
2     cd-3.3.1
7     cd-3.5.2
9    cd-3.10.1
1    cd-3.10.3
3   cd-3.10.10
11   cd-3.11.4
4    cd-3.12.0
10   cd-3.20.1

这是对这些数据进行排序的另一种方法(它稍微快一些,因为我们避免了 lambda),

d = df.versions.to_dict()
df.iloc[natsorted(d, key=d.get)]

      versions
8     ab-3.0.2
5     ab-5.2.1
0    cd-2.8.10
6     cd-3.1.3
2     cd-3.3.1
7     cd-3.5.2
9    cd-3.10.1
1    cd-3.10.3
3   cd-3.10.10
11   cd-3.11.4
4    cd-3.12.0
10   cd-3.20.1

推荐阅读