在熊猫中对字符串进行排序

时间:2019-08-17 09:37:37

标签: python pandas sorting dataframe

我的熊猫有一个数据框,我想按列对其进行排序。 如果我像下面的代码一样使用.sort_values()

df.sort_values(by='id')

我在“ id”列中得到的输出为:

1075_2016-06-01_0_1
1075_2016-06-01_10_1
1075_2016-06-01_10_2
1075_2016-06-01_11_1
1075_2016-06-01_11_2
1075_2016-06-01_1_1
1075_2016-06-01_1_2

我期望:

1075_2016-06-01_0_1
1075_2016-06-01_1_1
1075_2016-06-01_1_2
1075_2016-06-01_10_1
1075_2016-06-01_10_2
1075_2016-06-01_11_1
1075_2016-06-01_11_2

在熊猫中做到这一点的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

使用natsort的一种可能的解决方案,用于获取排序值的索引并通过loc更改原始DataFrame:

from natsort import index_natsorted, order_by_index

df2 = df.loc[order_by_index(df.index, index_natsorted(df['id']))]

或将所有值除以_,然后将列转换为整数,并将可选值转换为日期时间,对索引进行排序,最后将loc与原始DataFrame一起使用:

df1 = df['id'].str.split('_', expand=True)
df1[[0,2,3]] = df1[[0,2,3]].astype(int)
df1[1] = pd.to_datetime(df1[1])

df2 = df.loc[df1.sort_values([0,1,2,3]).index]
print (df2)
                     id
0   1075_2016-06-01_0_1
5   1075_2016-06-01_1_1
6   1075_2016-06-01_1_2
1  1075_2016-06-01_10_1
2  1075_2016-06-01_10_2
3  1075_2016-06-01_11_1
4  1075_2016-06-01_11_2

使用argsort进行排序和更改顺序的下一个解决方案是通过使用iloc进行位置索引来处理任何索引值:

f = lambda x: [int(x[0]), pd.to_datetime(x[1]), int(x[2]), int(x[3])]
df2 = df.iloc[df['id'].str.split('_').map(f).argsort()]
print (df2)
                     id
0   1075_2016-06-01_0_1
5   1075_2016-06-01_1_1
6   1075_2016-06-01_1_2
1  1075_2016-06-01_10_1
2  1075_2016-06-01_10_2
3  1075_2016-06-01_11_1
4  1075_2016-06-01_11_2

答案 1 :(得分:1)

非常感谢您!两种解决方案的组合有效:

df['sort_val']= df['id'].str.split('_') 
f = lambda x: [int(x[0]), pd.to_datetime(x[1]), int(x[2]), int(x[3])]
df['sort_val'] = df['sort_val'].map(f)
df.sort_values(by='sort_val').drop('sort_val',1)

答案 2 :(得分:0)

您可以先将每个下划线的值分开,然后对它们进行排序,例如:

df['sort_val'] = df['id'].str.split('_')
df = df.sort_values('sort_val').drop('sort_val', 1)

以上内容适用于任意数量的下划线分隔值。

这给我们:

>>> df
                     id
0   1075_2016-06-01_0_1
1  1075_2016-06-01_10_1
2  1075_2016-06-01_10_2
3  1075_2016-06-01_11_1
4  1075_2016-06-01_11_2
5   1075_2016-06-01_1_1
6   1075_2016-06-01_1_2
>>> df['sort_val'] = df['id'].str.split('_')
>>> df = df.sort_values('sort_val').drop('sort_val', 1)
>>> df
                     id
0   1075_2016-06-01_0_1
5   1075_2016-06-01_1_1
6   1075_2016-06-01_1_2
1  1075_2016-06-01_10_1
2  1075_2016-06-01_10_2
3  1075_2016-06-01_11_1
4  1075_2016-06-01_11_2