Manera más rápida de clasificar filas en subgrupos en el dataframe de pandas

Tengo un dataframe de pandas que se compone de diferentes subgrupos.

df = pd.DataFrame({ 'id':[1, 2, 3, 4, 5, 6, 7, 8], 'group':['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b'], 'value':[.01, .4, .2, .3, .11, .21, .4, .01] }) 

Quiero encontrar el rango de cada ID en su grupo con, por ejemplo, los valores más bajos son mejores. En el ejemplo anterior, en el grupo A, Id 1 tendría un rango de 1, Id 2 tendría un rango de 4. En el grupo B, Id 5 tendría un rango de 2, Id 8 tendría un rango de 1 y así en.

Ahora mismo evalúo los rangos por:

  1. Clasificación por valor.

    df.sort('value', ascending = True, inplace=True)

  2. Crear una función de clasificación (asume variables ya ordenadas)

    def ranker(df): df['rank'] = np.arange(len(df)) + 1 return df

  3. Aplique la función de clasificación en cada grupo por separado:

    df = df.groupby(['group']).apply(ranker)

Este proceso funciona pero es realmente lento cuando lo ejecuto en millones de filas de datos. ¿Alguien tiene alguna idea sobre cómo hacer que un ranking sea más rápido?

El rango es citonizado por lo que debe ser muy rápido. Y puede pasar las mismas opciones que df.rank() aquí están los documentos para el rank . Como puede ver, los desempates se pueden hacer de una de cinco maneras diferentes a través del argumento del method .

También es posible que simplemente quieras el .cumcount() del grupo.

 In [12]: df.groupby('group')['value'].rank(ascending=False) Out[12]: 0 4 1 1 2 3 3 2 4 3 5 2 6 1 7 4 dtype: float64 

Trabajando con un gran DataFrame (13 millones de líneas), el rango de método con groupby superó mis 8GB de RAM y tomó mucho tiempo. Encontré una solución menos codiciosa en la memoria, que puse aquí por si acaso:

 df.sort_values('value') tmp = df.groupby('group').size() rank = tmp.map(range) rank =[item for sublist in rank for item in sublist] df['rank'] = rank