问题描述
我是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.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)
重新编制索引后的输出:
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?