8 votes

Groupez plusieurs colonnes, puis agrégez un ensemble de colonnes dans Pandas (cela plante gravement par rapport à data.table de R)

Je suis relativement nouveau dans le monde de Python et j'essaie de l'utiliser comme plateforme de secours pour faire de l'analyse de données. J'utilise généralement data.table pour mes besoins en analyse de données.

Le problème est que lorsque j'exécute une opération de regroupement-agrégation sur un gros fichier CSV (randomisé, compressé, téléchargé à http://www.filedropper.com/ddataredact_1), Python lance:

grouping pandas return getattr(obj, method)(*args, **kwds) ValueError: les dimensions négatives ne sont pas autorisées

OU (j'ai même rencontré...)

Fichier "C:\Anaconda3\lib\site-packages\pandas\core\reshape\util.py", ligne 65, dans produit_cartesien pour i, x in enumerate(X)] Fichier "C:\Anaconda3\lib\site-packages\pandas\core\reshape\util.py", ligne 65, dans pour i, x in enumerate(X)] Fichier "C:\Anaconda3\lib\site-packages\numpy\core\fromnumeric.py", ligne 445, dans repeter return _wrapfunc(a, 'repeat', repeats, axis=axis) Fichier "C:\Anaconda3\lib\site-packages\numpy\core\fromnumeric.py", ligne 51, dans _wrapfunc return getattr(obj, method)(*args, **kwds) MemoryError

J'ai passé trois jours à essayer de réduire la taille du fichier (j'ai réussi à réduire la taille de 89%), à ajouter des points d'arrêt, à le déboguer, mais je n'ai pas pu faire avancer les choses.

Étonnamment, j'ai pensé à exécuter la même opération de regroupement/agrégation dans data.table en R, et cela a à peine pris 1 seconde. De plus, je n'ai pas eu à faire de conversion de types de données, etc., comme suggéré à https://www.dataquest.io/blog/pandas-big-data/.

J'ai également recherché d'autres fils de discussion : Eviter les problèmes de mémoire pour GroupBy sur un grand DataFrame Pandas, Pandas: df.groupby() est trop lent pour un ensemble de données volumineux. Des méthodes alternatives ?, et Pandas groupby avec sum() sur un grand fichier csv ?. Il semblerait que ces fils de discussion concernent davantage la multiplication de matrices. J'apprécierais que vous ne marquiez pas ceci comme un doublon.

Voici mon code Python :

finaldatapath = "..\Data_R"
ddata = pd.read_csv(finaldatapath +"\\"+"ddata_redact.csv", low_memory=False,encoding ="ISO-8859-1")

#avant optimisation : 353Mo
ddata.info(memory_usage="deep")

#optimiser le fichier : les types d'objets sont les plus grands coupables.
ddata_obj = ddata.select_dtypes(include=['object']).copy()

#Maintenant convertir ceci en type catégorie :
#Le type float n'a pas beaucoup aidé, donc je l'exclus ici.
for col in ddata_obj:
    del ddata[col]
    ddata.loc[:, col] = ddata_obj[col].astype('category')

#libérer la mémoire
del ddata_obj

#après optimisation : 39Mo
ddata.info(memory_usage="deep")

#Créer une liste de variables de regroupement :
group_column_list = [
                 "Business",
                 "Device_Family",
                 "Geo",
                 "Segment",
                 "Cust_Name",
                 "GID",
                 "Device ID",
                 "Seller",
                "C9Phone_Margins_Flag",
                 "C9Phone_Cust_Y_N",
                 "ANDroid_Lic_Type",
                 "Type",
                 "Term",
                 'Cust_ANDroid_Margin_Bucket',
                 'Cust_Mobile_Margin_Bucket',
# #                'Cust_Android_App_Bucket',
                 'ANDroind_App_Cust_Y_N'
]

print("Analyse des données en cours...")

def ddata_agg(x):
    names = {
        'ANDroid_Margin': x['ANDroid_Margin'].sum(),
        'Margins': x['Margins'].sum(),
        'ANDroid_App_Qty': x['ANDroid_App_Qty'].sum(),
        'Apple_Margin':x['Apple_Margin'].sum(),
       'P_Lic':x['P_Lic'].sum(),
       'Cust_ANDroid_Margins':x['Cust_ANDroid_Margins'].mean(),
       'Cust_Mobile_Margins':x['Cust_Mobile_Margins'].mean(),
       'Cust_ANDroid_App_Qty':x['Cust_ANDroid_App_Qty'].mean()
    }
    return pd.Series(names)

ddata=ddata.reset_index(drop=True)

ddata = ddata.groupby(group_column_list).apply(ddata_agg) 

Le code plante dans l'opération .groupby ci-dessus.

Est-ce que quelqu'un pourrait m'aider s'il vous plaît ? Comparé à mes autres messages, j'ai probablement passé le plus de temps sur ce message de StackOverflow, essayant de le corriger et d'apprendre de nouvelles choses sur Python. Cependant, j'ai atteint la saturation - cela me frustre encore plus parce que le package data.table de R traite ce fichier en moins de 2 secondes. Ce message ne concerne pas les pour et les contre de R et Python, mais l'utilisation de Python pour être plus productif.

Je suis complètement perdu et j'apprécierais toute aide.


Voici mon code data.table en R :

path_r = "../ddata_redact.csv"
ddata<-data.table::fread(path_r,stringsAsFactors=FALSE,data.table = TRUE, header = TRUE)

group_column_list <-c(
  "Business",
  "Device_Family",
  "Geo",
  "Segment",
  "Cust_Name",
  "GID",
  "Device ID",
  "Seller",
  "C9Phone_Margins_Flag",
  "C9Phone_Cust_Y_N",
  "ANDroid_Lic_Type",
  "Type",
  "Term",
  'Cust_ANDroid_Margin_Bucket',
  'Cust_Mobile_Margin_Bucket',
  # #                'Cust_Android_App_Bucket',
  'ANDroind_App_Cust_Y_N'
  )

    ddata<-ddata[, .(ANDroid_Margin = sum(ANDroid_Margin,na.rm = TRUE), 
Margins=sum(Margins,na.rm = TRUE), 
Apple_Margin=sum(Apple_Margin,na.rm=TRUE),  
Cust_ANDroid_Margins = mean(Cust_ANDroid_Margins,na.rm = TRUE),  
Cust_Mobile_Margins = mean(Cust_Mobile_Margins,na.rm = TRUE),
Cust_ANDroid_App_Qty = mean(Cust_ANDroid_App_Qty,na.rm = TRUE),
ANDroid_App_Qty=sum(ANDroid_App_Qty,na.rm = TRUE)
), 
by=group_column_list]

J'ai une machine Win10x64 avec 4 cœurs et 16Go de RAM. Je peux fournir tous les détails nécessaires aux experts.

Ajoutant au commentaire de Josemz, voici deux fils de discussion sur agg vs. apply : Quelle est la différence entre les fonctions agg et apply de pandas ? et Différence entre les fonctions apply() et aggregate() de Pandas

1voto

josemz Points 827

Je pense que ce que vous cherchez est agg au lieu de apply. Vous pouvez passer un dictionnaire qui fait correspondre les colonnes aux fonctions que vous voulez appliquer, donc je pense que cela fonctionnerait pour vous :

ddata = ddata.groupby(group_column_list).agg({
    'ANDroid_Margin'      : sum,
    'Margins'             : sum,
    'ANDroid_App_Qty'     : sum,
    'Apple_Margin'        : sum,
    'P_Lic'               : sum,
    'Cust_ANDroid_Margins': 'mean',
    'Cust_Mobile_Margins' : 'mean',
    'Cust_ANDroid_App_Qty': 'mean'})

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X