【问题标题】:Rank values in grouped data对分组数据中的值进行排名
【发布时间】:2019-12-24 03:08:47
【问题描述】:

我正在寻找一种有效的方法来重新编号 Python 中分组数据框的等级向量。

在一个简单的数据中,我首先根据countssoldier_type 进行排名。到目前为止这很简单! OTOH,我需要根据以下条件重新排列士兵:

如果soldier_type == S1,在regimenttrucks的每一组中,我希望它总是排名为1,然后从排名2开始重新排名其他士兵类型(从最高@ 987654328@ 最低)。

这是我解决这个问题的尝试:

import pandas as pd

from numpy.random import seed
from numpy.random import randint

seed(1234)

raw_data = {'regiment': ['51st', '51st', '51st', '51st', '51st', '51st', '51st', '51st', '51st', '51st', '51st', '51st'], 
            'trucks': ['MAZ-7310', 'MAZ-7310', 'MAZ-7310', 'MAZ-7310', 'Tatra 810', 'Tatra 810', 'Tatra 810', 'Tatra 810', 'ZIS-150', 'ZIS-150', 'ZIS-150', 'ZIS-150'],
            'soldier_type': ['S1', 'S2', 'S3', 'S4', 'S1', 'S3', 'S4', 'S5', 'S1', 'S2', 'S4', 'S5'],            
            'counts': randint(1,100,12)}


df = pd.DataFrame(raw_data, columns = ['regiment', 'trucks','soldier_type', 'counts'])


   regiment     trucks soldier_type  counts
0      51st   MAZ-7310           S1      48
1      51st   MAZ-7310           S2      84
2      51st   MAZ-7310           S3      39
3      51st   MAZ-7310           S4      54
4      51st  Tatra 810           S1      77
5      51st  Tatra 810           S3      25
6      51st  Tatra 810           S4      16
7      51st  Tatra 810           S5      50
8      51st    ZIS-150           S1      24
9      51st    ZIS-150           S2      27
10     51st    ZIS-150           S4      31
11     51st    ZIS-150           S5      44

def rank_soldier_type (df):

    df = df.assign(rank_ = df.groupby(['regiment','trucks'])['counts'].rank(ascending = False,method='dense'))

    return df #1st part
    #%%
    if  df.soldier_type != 'S1' and df.rank_ == 1 :

        df['new_rank_'] = 1
    else:
        df['new_rank_'] = df['rank_'].rank(ascending = False,method='dense')

    return df

df = rank_soldier_type(df)     

如果我运行此函数的第一部分,我可以创建 rank_ 列:

df = rank_soldier_type(df)  

   regiment     trucks soldier_type  counts  rank_
0      51st   MAZ-7310           S1      48    3.0
1      51st   MAZ-7310           S2      84    1.0
2      51st   MAZ-7310           S3      39    4.0
3      51st   MAZ-7310           S4      54    2.0
4      51st  Tatra 810           S1      77    1.0
5      51st  Tatra 810           S3      25    3.0
6      51st  Tatra 810           S4      16    4.0
7      51st  Tatra 810           S5      50    2.0
8      51st    ZIS-150           S1      24    4.0
9      51st    ZIS-150           S2      27    3.0
10     51st    ZIS-150           S4      31    2.0
11     51st    ZIS-150           S5      44    1.0

预期的输出;

        regiment     trucks soldier_type  counts  rank_  new_rank_
    0      51st   MAZ-7310           S1      48    3.0       1.0
    1      51st   MAZ-7310           S2      84    1.0       2.0
    2      51st   MAZ-7310           S3      39    4.0       4.0
    3      51st   MAZ-7310           S4      54    2.0       3.0
    4      51st  Tatra 810           S1      77    1.0       1.0
    5      51st  Tatra 810           S3      25    3.0       3.0
    6      51st  Tatra 810           S4      16    4.0       4.0
    7      51st  Tatra 810           S5      50    2.0       2.0
    8      51st    ZIS-150           S1      24    4.0       1.0
    9      51st    ZIS-150           S2      27    3.0       4.0 
    10     51st    ZIS-150           S4      31    2.0       3.0
    11     51st    ZIS-150           S5      44    1.0       2.0

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    通过添加 duplicated 来修复您的代码

    df['New']=df[df[['regiment', 'trucks']].duplicated()].\
                groupby(['regiment', 'trucks'])['counts'].rank(ascending=False, method='dense')+1
    df.New.fillna(1,inplace=True)
    df
    Out[35]: 
       regiment     trucks soldier_type  counts  New
    0      51st   MAZ-7310           S1      48  1.0
    1      51st   MAZ-7310           S2      84  2.0
    2      51st   MAZ-7310           S3      39  4.0
    3      51st   MAZ-7310           S4      54  3.0
    4      51st  Tatra 810           S1      77  1.0
    5      51st  Tatra 810           S3      25  3.0
    6      51st  Tatra 810           S4      16  4.0
    7      51st  Tatra 810           S5      50  2.0
    8      51st    ZIS-150           S1      24  1.0
    9      51st    ZIS-150           S2      27  4.0
    10     51st    ZIS-150           S4      31  3.0
    11     51st    ZIS-150           S5      44  2.0
    

    【讨论】:

    • 感谢您的解决方案。有没有可能像 OP 中的 if-else 时尚一样解决这个问题!我想了解您在这种情况下如何处理解决方案!
    • @Alexander if else,所以你的意思是 np.where?我的解决方案是排除每个组的第一行,然后我们对其余行进行排名,然后将 1 分配给第一行
    • 只要我可以使用 if else ,任何东西都可以工作。我更喜欢这种方式,因为我想在不同的条件下申请rank_soldier_type。所以我需要一个条件句。 np.where 也可以。您能否以def 格式发送您的解决方案?
    • @Alexander 当你使用 pandas 时,最好减少 apply 或 self-def 函数的使用,总是尝试在 pandas 中使用矢量化函数。
    • 哦,真的!不知道。我认为如果我只调用 self-def 函数,代码会更清晰,因为我们可以将很多东西放入并调用它们!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 2021-03-11
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多