Las pandas clasifican por columnas múltiples

Estoy tratando de clasificar un dataframe de pandas basado en dos columnas. Puedo clasificarlo en base a una columna, pero ¿cómo puedo clasificarlo en base a dos columnas? ‘SaleCount’, luego ‘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) 

salida de stream:

  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 

Estoy tratando de generar una salida como esta:

  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 

Otra forma sería convertir las columnas de interés en str y combinarlas concatenándolas. Conviértalos de nuevo a valores numéricos para poder diferenciarlos en función de su magnitud.

En method=dense , los rangos de valores duplicados se mantendrían sin cambios. (Aquí: 6)

Ya que desea clasificarlos en su orden descendente, especificar ascending=False en Series.rank() le permitirá obtener el resultado deseado.

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

introduzca la descripción de la imagen aquí

pd.factorize generará valores únicos para cada elemento único de un iterable. Solo necesitamos clasificar el orden que deseamos y luego factorizar. Para hacer varias columnas, convertimos el resultado ordenado en tuplas.

 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 

(La forma correcta de clasificar dos columnas int (no negativas) es según la respuesta de Nickil Maveli, para convertirlas en cuerdas, concatenarlas y devolverlas a int.)

Sin embargo, aquí hay un acceso directo si sabe que TotalRevenue está restringido a algún rango, por ejemplo, 0 a MAX_REVENUE = 100,000; Manipularlos directamente como enteros no negativos:

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