如何 pandas 对具有其中一列作为版本号的数据框进行排序?

How to pandas sort a dataframe that has one of the columns as version numbers?

我是 Python 的初学者。我正在尝试对 versions 列 -

上的数据框进行排序

print(df)

        versions         memory
0         10.0.0         107.07
1       10.0.0.1         110.11
2         10.0.2         110.56
3         10.0.4         116.27
4         10.1.0         116.17
5         10.1.2         113.98
6         10.1.4         113.27
7         10.2.0         103.32
8          9.9.2         112.02
9        9.9.2.3         112.28
10         9.9.4         114.45
11       9.9.4.1         114.32

使得结果数据帧为 -

        versions         memory
0          9.9.2         112.02
1        9.9.2.3         112.28
2          9.9.4         114.45
3        9.9.4.1         114.32
4         10.0.0         107.07
5       10.0.0.1         110.11
6         10.0.2         110.56
7         10.0.4         116.27
8         10.1.0         116.17
9         10.1.2         113.98
10        10.1.4         113.27
11        10.2.0         103.32

versions 列的数据类型是 object

我试过 -

df = df.sort_values('versions')

但这会使数据框保持不变。

也试过做-

from distutils.version import StrictVersion
df = sorted(df['ghost_version'], key=StrictVersion)

但在 ValueError: invalid version number '10.0.0.1'

时出错

有人可以指导吗?

谢谢

您可以创建由整数填充的元组,通过 Series.argsort and change order by DataFrame.iloc, last for defaut index use DataFrame.reset_index:

获取排序值的索引
df1 = (df.iloc[df['versions'].apply(lambda x: tuple(map(int, x.split(".")))).argsort()]
         .reset_index(drop=True))

或将辅助列与 DataFrame.sort_values 一起使用,最后删除列:

df['tmp'] = df['versions'].apply(lambda x: tuple(map(int, x.split("."))))
df1 = df.sort_values('tmp').drop('tmp', axis=1).reset_index(drop=True)

对于排序值的顺序也可以使用 LooseVersion:

from distutils.version import LooseVersion

df1 = df.iloc[df['versions'].apply(LooseVersion).argsort()].reset_index(drop=True)


    versions  memory
0      9.9.2  112.02
1    9.9.2.3  112.28
2      9.9.4  114.45
3    9.9.4.1  114.32
4     10.0.0  107.07
5   10.0.0.1  110.11
6     10.0.2  110.56
7     10.0.4  116.27
8     10.1.0  116.17
9     10.1.2  113.98
10    10.1.4  113.27
11    10.2.0  103.32
df['nVersion'] = df['version'].apply(lambda x: float(str(x.split('.')[0]) + '.' + str(''.join(x.split('.')[1:]))))

在此之后,您可以对 nVersion 列进行排序,然后将其删除。

给出列号而不是列名

df = df.sort_values('0')

请也看看这个解决方案

使用distutils.version.LooseVersion的一种方式:

from distutils.version import LooseVersion

df["versions"] = df["versions"].apply(LooseVersion)
new_df = df.sort_values("versions")
# new_df["version"] = new_df["verions"].astype(str)
# if you don't want to have LooseVersion objects
print(new_df)

或从 pandas => 1.1.0 开始,sort_values 可以接受 key,类似于 sorted,但需要矢量化可调用对象。

f = lambda x: [LooseVersion(i) for i in x]
new_df = df.sort_values("versions", key=f)
print(new_df)

如果你想要一个全新的 RangeIndex:

new_df = new_df.reset_index(drop=True)

re-indexing后的输出:

    versions  memory
0      9.9.2  112.02
1    9.9.2.3  112.28
2      9.9.4  114.45
3    9.9.4.1  114.32
4     10.0.0  107.07
5   10.0.0.1  110.11
6     10.0.2  110.56
7     10.0.4  116.27
8     10.1.0  116.17
9     10.1.2  113.98
10    10.1.4  113.27
11    10.2.0  103.32