web-dev-qa-db-ja.com

Pandas複数の列でランク付け

pandasデータフレームを2つの列に基づいてランク付けしようとしています。1つの列に基づいてランク付けできますが、2つの列に基づいてランク付けするにはどうすればよいですか? 'SaleCount'、次に 'TotalRevenue '?

import pandas as pd

df = pd.DataFrame({'TotalRevenue':[300,9000,1000,750,500,2000,0,600,50,500],
    'Date':['2016-12-02' for i in range(10)],
    'SaleCount':[10,100,30,35,20,100,0,30,2,20],
    'shops':['S3','S2','S1','S5','S4','S8','S6','S7','S9','S10']})

df['Rank'] = df.SaleCount.rank(method='dense',ascending = False).astype(int)

#df['Rank'] = df.TotalRevenue.rank(method='dense',ascending = False).astype(int)
df.sort_values(['Rank'], inplace=True)

print(df)

現在の出力:

    Date        SaleCount   TotalRevenue    shops   Rank
1   2016-12-02  100          9000            S2      1
5   2016-12-06  100          2000            S8      1
3   2016-12-04  35           750             S5      2
2   2016-12-03  30           1000            S1      3
7   2016-12-08  30           600             S7      3
9   2016-12-10  20           500             S10     4
4   2016-12-05  20           500             S4      4
0   2016-12-01  10           300             S3      5
8   2016-12-09  2            50              S9      6
6   2016-12-07  0            0               S6      7

私は次のような出力を生成しようとしています:

    Date        SaleCount   TotalRevenue    shops   Rank
1   2016-12-02  100          9000            S2      1
5   2016-12-02  100          2000            S8      2
3   2016-12-02  35           750             S5      3
2   2016-12-02  30           1000            S1      4
7   2016-12-02  30           600             S7      5
9   2016-12-02  20           500             S10     6
4   2016-12-02  20           500             S4      6
0   2016-12-02  10           300             S3      7
8   2016-12-02  2            50              S9      8
6   2016-12-02  0            0               S6      9
6
Anoop

もう1つの方法は、対象の両方の列をstrに型キャストし、それらを連結して結合することです。これらを数値に変換し直して、大きさに基づいて区別できるようにします。

_method=dense_では、重複する値のランクは変更されません。 (ここ:6)

これらを降順でランク付けする必要があるため、 Series.rank() で_ascending=False_を指定すると、目的の結果が得られます。

_col1 = df["SaleCount"].astype(str) 
col2 = df["TotalRevenue"].astype(str)
df['Rank'] = (col1+col2).astype(int).rank(method='dense', ascending=False).astype(int)
df.sort_values('Rank')
_

enter image description here

10
Nickil Maveli

pd.factorize は、iterableの一意の要素ごとに一意の値を生成します。必要な順序で並べ替えてから、因数分解するだけです。複数の列を作成するために、ソートされた結果をタプルに変換します。

cols = ['SaleCount', 'TotalRevenue']
tups = df[cols].sort_values(cols, ascending=False).apply(Tuple, 1)
f, i = pd.factorize(tups)
factorized = pd.Series(f + 1, tups.index)

df.assign(Rank=factorized)

         Date  SaleCount  TotalRevenue shops  Rank
1  2016-12-02        100          9000    S2     1
5  2016-12-02        100          2000    S8     2
3  2016-12-02         35           750    S5     3
2  2016-12-02         30          1000    S1     4
7  2016-12-02         30           600    S7     5
4  2016-12-02         20           500    S4     6
9  2016-12-02         20           500   S10     6
0  2016-12-02         10           300    S3     7
8  2016-12-02          2            50    S9     8
6  2016-12-02          0             0    S6     9
8
piRSquared

これを行う一般的な方法は、タイプに関係なく、目的のフィールドをタプルにグループ化することです。

df["Rank"] = df[["SaleCount","TotalRevenue"]].apply(Tuple,axis=1)\
             .rank(method='dense',ascending=False).astype(int)

df.sort_values("Rank")

   TotalRevenue        Date  SaleCount shops  Rank
1          9000  2016-12-02        100    S2     1
5          2000  2016-12-02        100    S8     2
3           750  2016-12-02         35    S5     3
2          1000  2016-12-02         30    S1     4
7           600  2016-12-02         30    S7     5
4           500  2016-12-02         20    S4     6
9           500  2016-12-02         20   S10     6
0           300  2016-12-02         10    S3     7
8            50  2016-12-02          2    S9     8
6             0  2016-12-02          0    S6     9
3
B. M.

(2つの(非負の)int列をランク付けする正しい方法は、Nickil Maveliの回答に従って、それらを文字列にキャストし、連結して、intにキャストバックすることです。)

ただしTotalRevenueが特定の範囲に制限されていることがわかっている場合のショートカットです例: 0からMAX_REVENUE = 100,000;それらを非負の整数として直接操作します。

df['Rank'] = (df['SaleCount']*MAX_REVENUE + df['TotalRevenue']).rank(method='dense', ascending=False).astype(int)

df.sort_values('Rank2')
1
smci

sort_values + GroupBy.ngroup

これにより、denseランキングが得られます。

グループ化の前に、列を目的の順序で並べ替える必要があります。 groupby内でsort=Falseを指定すると、この並べ替えが尊重され、並べ替えられたDataFrame内に表示される順序でグループにラベルが付けられます。

cols = ['SaleCount', 'TotalRevenue']
df['Rank'] = df.sort_values(cols, ascending=False).groupby(cols, sort=False).ngroup() + 1

出力:

print(df.sort_values('Rank'))

   TotalRevenue        Date  SaleCount shops  Rank
1          9000  2016-12-02        100    S2     1
5          2000  2016-12-02        100    S8     2
3           750  2016-12-02         35    S5     3
2          1000  2016-12-02         30    S1     4
7           600  2016-12-02         30    S7     5
4           500  2016-12-02         20    S4     6
9           500  2016-12-02         20   S10     6
0           300  2016-12-02         10    S3     7
8            50  2016-12-02          2    S9     8
6             0  2016-12-02          0    S6     9
0
ALollz