按表示(主要)数字的字符串列对Pandas DataFrame排序



我有类似的数据。

data = [
dict(name = 'test1', index = '1' , status='fail'),
dict(name = 'test3', index = '3', status='pass'),
dict(name = 'test1', index = '11', status='pass'),
dict(name = 'test1', index = '1 2 14 56', status='fail'),
dict(name = 'test3', index = '20', status='fail'),
dict(name = 'test1', index = '2' , status='fail'),
dict(name = 'test3', index = '5:1:50', status='pass'),]

注意,"index"列的类型是str。由于它有一些不规则的条目,我无法轻松地将其转换为数字类型。(如果可能的话,我不会有这个问题。(

首先,我将其转换为DataFrame:

df = pd.DataFrame(data)

这给了我

name    index     status
0   test1   1         fail
1   test3   3         pass
2   test1   11        pass
3   test1   1 2 14 56 fail
4   test3   20        fail
5   test1   2         fail
6   test3   5:1:50    pass

接下来我对它进行排序:

df1 = df.sort_values(by=['name','index'])

由于"index"列是"str",因此将按词法进行排序。

name    index     status
0   test1   1         fail
3   test1   1 2 14 56 fail
2   test1   11        pass
5   test1   2         fail
4   test3   20        fail
1   test3   3         pass
6   test3   5:1:50    pass

我真正想要的是:

name    index     status
0   test1   1         fail
5   test1   2         fail
2   test1   11        pass
3   test1   1 2 14 56 fail
1   test3   3         pass
4   test3   20        fail
6   test3   5:1:50    pass

第4行和第7行(DF指数3和6(中的不规则值也可以进入每个测试组的开头。关键是,可以转换为数字表示的"索引"列的值应按数字排序。最好是在适当的地方。怎样

这将根据名称和临时列(__ix(进行排序,该列是在每个'index'字符串中找到的第一个整数(连续数字(:

更新:您也可以使用:

df = (
df
.assign(
__ix=df['index'].str.extract(r'([0-9]+)').astype(int)
)
.sort_values(['name', '__ix'])
.drop('__ix', axis=1)  # optional: remove the tmp column
.reset_index(drop=True)  # optional: leaves the index scrambled
)

原件

df = (
df
.assign(
__ix=df['index']
.apply(lambda s: int(re.match(r'D*(d+)', s).group(0)))
)
.sort_values(['name', '__ix'])
.drop('__ix', axis=1)
.reset_index(drop=True)
)

关于您的数据(感谢您提供了一个简单可复制的示例(,首先检查__ix列是什么:

df['index'].apply(lambda s: int(re.match(r'D*(d+)', s).group(0)))
# out:
0     1
1     3
2    11
3     1
4    20
5     2
6     5

排序后,您的df变为:

name      index status
0  test1          1   fail
1  test1  1 2 14 56   fail
2  test1          2   fail
3  test1         11   pass
4  test3          3   pass
5  test3     5:1:50   pass
6  test3         20   fail

一种可能性是创建一列,提供索引的长度。

df['sort'] = df['index'].str.len()
df['sort2'] = df['index'].str[0]
df1 = df.sort_values(by=['name','sort','sort2'])
df1 = df1.drop(columns = ['sort','sort2'])

最新更新