[PYTHON] pandas idxmax est lent

Contexte

Lors du traitement de Big Data au travail J'ai remarqué que le traitement était lent et je cherchais le criminel. J'ai remarqué que __idxmax () __ dans la bibliothèque pandas est lent. </ font>

Bien sûr, par rapport à max, il existe un processus pour renvoyer l'index de la valeur max, il est donc naturel qu'il soit plus lent. J'ai essayé de vérifier à quel point c'était lent.

Connaissances préalables

Le traitement de __max () __ et __idxmax () __ des pandas est le suivant.

import pandas as pd
import numpy as np

#Générer une trame de données 10x5 d'entiers aléatoires entre 0 et 100
data = np.random.randint(0,100,[10,5])
df = pd.DataFrame(data,
                  index=['A','B','C','D','E','F','G','H','I','J'],
                  columns=['a','b','c','d','e'])

print(df)
print(df.max())
print(df.idxmax())

__max () __ renvoie la valeur maximale pour chaque colonne, __idxmax () __ renvoie l'index maximum pour chaque colonne

C'est une fonction appelée.

Maintenant, agrandissons la trame de données et mesurons le temps de traitement.

Mesure du temps de traitement de max () et idxmax ()

import pandas as pd
import numpy as np
import time

arr = np.random.randint(0,100,[10**5,10**4],dtype='int8')
df = pd.DataFrame(arr, dtype='int8')
df.info()
#<class 'pandas.core.frame.DataFrame'>
#RangeIndex: 100000 entries, 0 to 99999
#Columns: 10000 entries, 0 to 9999
#dtypes: int8(10000)
#memory usage: 953.7 MB

ts = time.time()
df.max()
te =time.time()
print('max()_time:',te-ts)
#max()_time: 10.67

ts = time.time()
df.idxmax()
te =time.time()
print('idxmax()_time:',te-ts)
#idxmax()_time: 19.08

L'expérience ci-dessus Pour une trame de données d'environ 1 Go C'est le résultat de la mesure du temps de traitement de __max () __ et __idxmax () __.

__idxmax () __ 19,08 ÷ 10,67 = __1,78 fois __ </ font> J'ai trouvé que le processus était lent.

Au fait, les spécifications de la machine sont Modèle MacBookPro 2018, processeur: Intel Core i5 2,3 GHz, mémoire: 8 Go 2133 MHz LPDDR3 est (Il y avait un décalage horaire 6 fois sur le PC Windows de mon entreprise.)

Jetons un coup d'œil au contenu de la fonction idxmax () pour voir si cela peut être fait plus rapidement.

Code source pour idxmax ()
import inspect
print(inspect.getsource(pd.DataFrame.idxmax))

Après avoir exécuté cela, le code source renvoyé est le suivant.

def idxmax(self, axis=0, skipna=True):
    """
    Return index of first occurrence of maximum over requested axis.
    NA/null values are excluded.

    Parameters
    ----------
    axis : {0 or 'index', 1 or 'columns'}, default 0
        0 or 'index' for row-wise, 1 or 'columns' for column-wise
    skipna : boolean, default True
        Exclude NA/null values. If an entire row/column is NA, the result
        will be NA.

    Returns
    -------
    idxmax : Series

    Raises
    ------
    ValueError
        * If the row/column is empty

    See Also
    --------
    Series.idxmax

    Notes
    -----
    This method is the DataFrame version of ``ndarray.argmax``.
    """
    axis = self._get_axis_number(axis)
    indices = nanops.nanargmax(self.values, axis=axis, skipna=skipna)
    index = self._get_axis(axis)
    result = [index[i] if i >= 0 else np.nan for i in indices]
    return Series(result, index=self._get_agg_axis(axis))

Il est écrit comme une version de trame de données de la fonction __argmax () __ de ndarray. Bien sûr, c'était comme prévu, je voudrais donc comparer le temps de traitement de __max () __ et __argmax () __.

Mesure du temps de traitement de max () et idxmax ()

ts = time.time()
_max = np.max(arr,axis=0)
te =time.time()
print('max()_time:',te-ts)
#max()_time: 0.85

ts = time.time()
_argmax = np.argmax(arr,axis=0)
te =time.time()
print('argmax()_time:',te-ts)
#argmax()_time: 13.70

Le résultat est __argmax () __ 13,70 ÷ 0,85 = __ 16,11 fois __ </ font> J'ai trouvé que le processus était lent.

Considération

-Les deux sont plus rapides que la trame de données. ・ Max est extrêmement plus rapide que idxmax lors de l'utilisation de ndarray.

Je comprends.

En tant que cause, Puisque idxmax est un processus qui ne renvoie que l'index des premières données lorsqu'il y a la même valeur maximale, Je pense que le temps de traitement est plus long de ce montant.

Si vous modifiez la plage et la taille des nombres aléatoires dans la trame de données, cet agrandissement changera considérablement, donc Le discours quantitatif est difficile, Une chose à dire est que si vous n'utilisez pas de traitement spécifique aux dataframe (tel que groupby) Il vaut mieux ne pas en faire une trame de données inutilement.