Более быстрый способ ранжирования строк в подгруппах в pandas dataframe

У меня есть кадр данных pandas, который состоит из разных подгрупп.

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

Я хочу найти ранг каждого идентификатора в своей группе, скажем, более низкие значения. В приведенном выше примере в группе A Id 1 будет иметь ранг 1, Id 2 будет иметь ранг 4. В группе B Id 5 будет иметь ранг 2, Id 8 будет иметь ранг 1 и так далее на.

Сейчас я оцениваю ряды:

  • Сортировка по значению.

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

  • Создайте функцию ранжирования (предполагается, что уже отсортированные переменные)

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

  • Применить функцию ранжирования для каждой группы отдельно:

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

Этот процесс работает, но он очень медленный, когда я запускаю его на миллионы строк данных. Есть ли у кого-нибудь идеи о том, как сделать более быструю функцию ранкера.

Ответ 1

rank cythonized, поэтому он должен быть очень быстрым. И вы можете передать те же параметры, что и df.rank() здесь являются документами для rank. Как вы можете видеть, тай-брейки могут выполняться одним из пяти способов с помощью аргумента method.

Также возможно, что вы просто хотите .cumcount() группы.

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

Ответ 2

Работа с большим DataFrame (13 миллионов строк), ранжирование метода с groupby превысило мой 8 ГБ оперативной памяти, и это заняло очень много времени. Я нашел обходное решение менее жадным в памяти, которое я здесь на всякий случай:

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