熊猫如何对具有列之一作为版本号的数据框进行排序?

问题描述

我是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获取排序值的索引,并通过DataFrame.iloc更改顺序,最后使用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
,

使用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.0sort_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)

重新编制索引后的输出:

    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')

也请研究此解决方案

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