簡體   English   中英

按代表(主要)數字的字符串列對 Pandas DataFrame 進行排序?

[英]Sort Pandas DataFrame by string column that represents (mostly) numbers?

我有類似的數據。

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'),]

請注意,“索引”列的類型是 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)中的不規則值也可以 go 到每個測試組的開頭。 關鍵點是,可以轉換為數字表示的“索引”列的值應按數字排序。 最好就地。 如何?

一種可能性是創建一個列,該列將為您提供索引的長度。

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'])

這將按名稱和臨時列 ( __ix ) 排序,該列是在每個'index'字符串中找到的第一個 integer (連續數字):

更新:您還可以使用:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM