Python Pandas Dataframe idxmax работает очень медленно. Альтернативы? - PullRequest
1 голос
/ 05 августа 2020

Я пытаюсь выбрать строки из групп по максимальному значению, используя df.loc[df.groupby(keys)['column'].idxmax()].

Однако я обнаружил, что df.groupby(keys)['column'].idxmax() занимает очень много времени в моем наборе данных из примерно 27 миллионов строк . Интересно, что запуск df.groupby(keys)['column'].max() в моем наборе данных занимает всего 13 секунд, а запуск df.groupby(keys)['column'].idxmax() занимает 55 минут. Я не понимаю, почему возврат индексов строк занимает в 250 раз больше времени, чем возврат значения из строки. Может быть, я могу что-то сделать, чтобы ускорить idxmax?

Если нет, есть ли альтернативный способ выбора строк из групп по максимальному значению, который может быть быстрее, чем использование idxmax?

Для дополнительная информация, я использую два ключа и отсортировал фрейм данных по этим ключам до операций groupby и idxmax. Вот как это выглядит в Jupyter Notebook:

import pandas as pd

df = pd.read_csv('/data/Broadband Data/fbd_us_without_satellite_jun2019_v1.csv', encoding='ANSI', \
    usecols=['BlockCode', 'HocoNum', 'HocoFinal', 'TechCode', 'Consumer', 'MaxAdDown', 'MaxAdUp'])
%%time
df = df[df.Consumer == 1]
df.sort_values(['BlockCode', 'HocoNum'], inplace=True)
print(df)
              HocoNum                  HocoFinal        BlockCode  TechCode
    4631064    130077                  AT&T Inc.   10010201001000        10   
    4679561    130077                  AT&T Inc.   10010201001000        11   
    28163032   130235     Charter Communications   10010201001000        43   
    11134756   131480  WideOpenWest Finance, LLC   10010201001000        42   
    11174634   131480  WideOpenWest Finance, LLC   10010201001000        50   
    ...           ...                        ...              ...       ...   
    15389917   190062          Broadband VI, LLC  780309900000014        70   
    10930322   130081    ATN International, Inc.  780309900000015        70   
    15389918   190062          Broadband VI, LLC  780309900000015        70   
    10930323   130081    ATN International, Inc.  780309900000016        70   
    15389919   190062          Broadband VI, LLC  780309900000016        70   

              Consumer  MaxAdDown  MaxAdUp  
    4631064          1        6.0    0.512  
    4679561          1       18.0    0.768  
    28163032         1      940.0   35.000  
    11134756         1     1000.0   50.000  
    11174634         1     1000.0   50.000  
    ...            ...        ...      ...  
    15389917         1       25.0    5.000  
    10930322         1       25.0    5.000  
    15389918         1       25.0    5.000  
    10930323         1       25.0    5.000  
    15389919         1       25.0    5.000  

    [26991941 rows x 7 columns]
    Wall time: 21.6 s

%time df.groupby(['BlockCode', 'HocoNum'])['MaxAdDown'].max()

    Wall time: 13 s
    BlockCode        HocoNum
    10010201001000   130077       18.0
                     130235      940.0
                     131480     1000.0
    10010201001001   130235      940.0
    10010201001002   130077        6.0
                                 ...  
    780309900000014  190062       25.0
    780309900000015  130081       25.0
                     190062       25.0
    780309900000016  130081       25.0
                     190062       25.0
    Name: MaxAdDown, Length: 20613795, dtype: float64

%time df.groupby(['BlockCode', 'HocoNum'])['MaxAdDown'].idxmax()

Wall time: 55min 24s
BlockCode        HocoNum
10010201001000   130077      4679561
                 130235     28163032
                 131480     11134756
10010201001001   130235     28163033
10010201001002   130077      4637222
                              ...   
780309900000014  190062     15389917
780309900000015  130081     10930322
                 190062     15389918
780309900000016  130081     10930323
                 190062     15389919
Name: MaxAdDown, Length: 20613795, dtype: int64

В самых первых строках данных вы увидите две записи для AT&T в одном и том же BlockCode, одну для MaxAdDown со скоростью 6 Мбит / с и одну для 18 Мбит / с. Я хочу сохранить строку 18 Мбит / с и отбросить строку 6 Мбит / с, чтобы для каждой компании на каждый блок-код была одна строка с максимальным значением MaxAdDown. Мне нужна вся строка, а не только значение MaxAdDown.

1 Ответ

2 голосов
/ 05 августа 2020

отсортировать и удалить дубликаты:

df.sort('MaxAdDown').drop_duplicates(['BlockCode', 'HocoNum'], keep='last')
...