我有类似的数据。
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'])