在 Pandas 中对包含数字和分隔符的字符串进行排序

Posted

技术标签:

【中文标题】在 Pandas 中对包含数字和分隔符的字符串进行排序【英文标题】:Sort Strings Containing Numbers and Delimeters in Pandas 【发布时间】:2019-12-18 02:26:03 【问题描述】:

我在工作中遇到了一个与排序有关的问题。我目前正在使用 Pandas 来保存我们的数据,我需要对包含带有数字和分隔符的字符串的列进行排序。

我已经尝试在要排序的列上使用 vanilla df.sort_values('Field Name'),但是出现了一些不需要的结果。

Python 格式的样本数据:

import pandas as pd
lis=[]
for i in ['99','100','101','102']:
    for j in map(str,[1,2,3,4,5,6,7,8,10,20,22,21,34]):
        for k in map(str,[1,2,11,12,22,23,33,16,17]):
            lis.append(i+'_'+j+'-'+k)
y = pd.DataFrame(dict(Field=lis))
y.sort_values('Field')

示例输出:

         Field
0      100_1-1
1     100_1-11
2     100_1-12
3     100_1-16
4     100_1-17
5      100_1-2
6     100_1-22
7     100_1-23
8     100_1-33
9     100_10-1
10   100_10-11
11   100_10-12
12   100_10-16
13   100_10-17
14    100_10-2
15   100_10-22
16   100_10-23
17   100_10-33
18     100_2-1
19    100_2-11
20    100_2-12
21    100_2-16
22    100_2-17
....

从这里可以看出,列表应该以“99”字符串开头。此外,您在 100_1-2 之前有 100_1-11、100_1-12、100_1-13。

我可以用下面的方法解决第一个问题,理论上如果我知道分隔符和分隔符的数量,那么我可以迭代地继续这样做,直到得到我想要的结果。

y.reindex(y['Field'].str.split('_',1,expand=True)[0].astype(int).sort_values(0).index).reset_index(drop=True)

但由于可能会使用分隔符“_”和“-”,所以它们不一定会在我收到的数据中使用,我也不知道只有 2 个分隔符。所以理论上我会得到如下糟糕的结果:

100_1_22-12-34:5

我仍然需要能够按预期对它们进行排序。

但是,有没有办法使用 Pandas 以更一般的形式获得我想要的结果?明确地说,我希望所有数字都按预期排列,代码尽可能少。

【问题讨论】:

不错的第一篇文章,感谢您提供良好的minimal reproducible example 和问题描述以及演示数据/想要的输出 【参考方案1】:

您需要将字符串数字转换为整数,然后将它们拆分为所有不同的字符。使用 int 的元组进行排序:

你可以这样做 f.e.像这样:

import pandas as pd
lis=[]

# mix up numbers / strings and values
for i in ['103','99','102','101']:
    for j in map(str,[10,2,34,4,5,1,22,21,3]):
        for k in map(str,[1,2,33,16,17]):
            lis.append(i+'_'+j+'-'+k)
df = pd.DataFrame(dict(Field=lis))

# split mixed up stuff using regex ('-' first so it does NOT denote a char-range)
# convert all remainders to int and make them a tuple to sort on (seperate column)
df["tup"] = df["Field"].str.split(r"[-_:]").apply(lambda x: tuple(map(int, x)))
# sort on seperate column
df = df.sort_values("tup")
print(df)

输出:

[180 rows x 1 columns]
        Field            tup
70     99_1-1     (99, 1, 1)
71     99_1-2     (99, 1, 2)
73    99_1-16    (99, 1, 16)
74    99_1-17    (99, 1, 17)
72    99_1-33    (99, 1, 33)
50     99_2-1     (99, 2, 1)
51     99_2-2     (99, 2, 2)
53    99_2-16    (99, 2, 16)
54    99_2-17    (99, 2, 17)
..        ...            ...
34  103_22-17  (103, 22, 17)
32  103_22-33  (103, 22, 33)
10   103_34-1   (103, 34, 1)
11   103_34-2   (103, 34, 2)
13  103_34-16  (103, 34, 16)
14  103_34-17  (103, 34, 17)
12  103_34-33  (103, 34, 33)

[180 rows x 2 columns]

排序前:

         Field
0     103_10-1
1     103_10-2
2    103_10-33
3    103_10-16
4    103_10-17
5      103_2-1
..         ...
173  101_21-16
174  101_21-17
175    101_3-1
176    101_3-2
177   101_3-33
178   101_3-16
179   101_3-17

【讨论】:

感谢帕特里克的回答。我想如果不知道分隔符,就没有办法做到这一点。这是我需要与数据创建者沟通的内容。

以上是关于在 Pandas 中对包含数字和分隔符的字符串进行排序的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS中对包含数字和名称的字符串数组进行排序

如何在 Python Pandas 中使用逗号作为小数分隔符的浮点格式?

在 pandas 中对函数进行矢量化

如何在 Pandas 中对时间序列进行切片

pandas中对日期型数据进行处理

15、pandas的设置数字格式,小数位数、百分号、千位分隔符