2015-12-09 3 views
4

J'ai un dataframe et je dois filtrer selon les conditions suivantesFiltrage d'une grande dataframe en pandas géants à l'aide de multitraitement

CITY == 'Mumbai' & LANGUAGE == 'English' & GENRE == 'ACTION' & count_GENRE >= 1 
CITY == 'Mumbai' & LANGUAGE == 'English' & GENRE == 'ROMANCE' & count_GENRE >= 1 
CITY == 'Mumbai' & LANGUAGE == 'Hindi' & count_LANGUAGE >= 1 & GENRE == 'ACTION' 

quand je suis en train de le faire par

df1 = df.query(condition1) 
    df2 = df.query(condition2) 

Je suis obtenir une erreur de mémoire (puisque la taille de ma base de données est énorme). Je prévoyais d'aller en filtrant l'état principal puis la sous-condition, de sorte que la charge soit moindre et les performances meilleures.

En analysant les conditions ci-dessus, en quelque sorte réussi à obtenir

main_filter = "CITY == 'Mumbai'" 
sub_cond1 = "LANGUAGE == 'English'" 
sub_cond1_cond1 = "GENRE == 'ACTION' & count_GENRE >= 1" 
sub_cond1_cond2 = "GENRE == 'ROMANCE' & count_GENRE >= 1" 
sub_cond2 = "LANGUAGE == 'Hindi' & count_LANGUGE >= 1" 
sub_cond2_cond1 = "GENRE == 'COMEDY'" 

pense donc comme une structure d'arbre (non binaire bien sûr, et en fait il n'est pas un arbre du tout).

Maintenant, je veux suivre une méthode de multitraitement (profondeur - sous-processus sous subprocess)

Maintenant, je veux quelque chose comme

on level 1 
df = df_main.query(main_filter) 
on level 2 
df1 = df.query(sub_cond1) 
df2 = df.query(sub_cond2) 
onlevel 3 
    df11 = df1.query(sub_cond1_cond1) 
    df12 = df1.query(sub_cond1_cond2) 
    df21 = df2.query(sub_cond2_cond1) ######like this 

Alors problème est de savoir comment passer des conditions correctement à chaque niveau (si Je vais stocker toutes les conditions dans une liste (en fait même pas pensé à ce sujet)). NB: le résultat de chaque filtrage doit être exporté pour séparer les csv distincts.

Ex:

df11.to_csv('CITY == 'Mumbai' & LANGUAGE == 'English' & GENRE == 'ACTION' & count_GENRE >= 1') 

En entrée, je ne sais pas comment suivre multitraitement (sa syntaxe & voie d'exécution, etc. notamment pour cela). Mais a obtenu la tâche malheureusement. Par conséquent, pas en mesure d'afficher des codes.

Donc, n'importe qui peut donner un exemple de ligne de code pour y parvenir.

Si vous avez une meilleure idée (objet de classe ou déplacement de noeud), veuillez suggérer.

+0

Que signifie "énorme"? Avez-vous un numéro? par exemple.taille de la mémoire ou lignes * cols dans la trame de données? –

+0

@ SteveMisuta-En fait, il contient 160 millions d'enregistrements appx. et et je dois courir 2 3 fichiers de plus .py à la fois qui accèdent à cet dataframe en interne et simultanément. C'est là que j'obtiens l'erreur de mémoire (hors capacité de RAM). ANd je ne peux rien faire à ce sujet (séparément alll tous ces fichiers py) – Satya

+0

@ SteveMisuta-si vous avez une idée comme façon d'itération de liste, puis en vérifiant d'abord char (si commence par sub_ ou sub_cond1 comme ça). Puis aussi je vais bien avec that.please suggèrent. – Satya

Répondre

13

Cela ressemble à un problème approprié pour dask, le module python qui vous aide à traiter des données plus grandes que la mémoire.

Je vais montrer comment résoudre ce problème en utilisant le dask.dataframe. Commençons par créer des données:

import pandas as pd 
from collections import namedtuple 
Record = namedtuple('Record', "CITY LANGUAGE GENRE count_GENRE count_LANGUAGE") 

cities = ['Mumbai', 'Chennai', 'Bengalaru', 'Kolkata'] 
languages = ['English', 'Hindi', 'Spanish', 'French'] 
genres = ['Action', 'Romance', 'Comedy', 'Drama'] 

import random 

df = pd.DataFrame([Record(random.choice(cities), 
          random.choice(languages), 
          random.choice(genres), 
          random.choice([1,2,3]), 
          random.choice([1,2,3])) for i in range(4000000)]) 

df.to_csv('temp.csv', index=False)  
print(df.head()) 

     CITY LANGUAGE GENRE count_GENRE count_LANGUAGE 
0 Chennai Spanish Action   2    1 
1 Bengalaru English Drama   2    3 
2 Kolkata Spanish Action   2    1 
3  Mumbai French Romance   1    2 
4 Chennai French Action   2    3 

Les données créées ci-dessus ont 4 millions de lignes et occupent 107 Mo. Ce n'est pas plus grand que la mémoire, mais assez bon à utiliser dans cet exemple.

Ci-dessous je montre la transcription d'une session python où je les données filtré selon les critères de la question:

>>> import dask.dataframe as dd 
>>> dask_df = dd.read_csv('temp.csv', header=0) 
>>> dask_df.npartitions 
4 

# We see above that dask.dataframe has decided to split the 
# data into 4 partitions 

# We now execute the query: 
>>> result = dask_df[(dask_df['CITY'] == 'Mumbai') & 
...     (dask_df['LANGUAGE'] == 'English') & 
...     (dask_df['GENRE'] == 'Action') & 
...     (dask_df['count_GENRE'] > 1)] 
>>> 

# The line above takes very little time to execute. In fact, nothing has 
# really been computed yet. Behind the scenes dask has create a plan to 
# execute the query, but has not yet pulled the trigger. 

# The result object is a dask dataframe: 
>>> type(result) 
<class 'dask.dataframe.core.DataFrame'> 
>>> result 
dd.DataFrame<series-slice-read-csv-temp.csv-fc62a8c019c213f4cd106801b9e45b29[elemwise-cea80b0dd8dd29ae325a9db1896b027c], divisions=(None, None, None, None, None)> 

# We now pull the trigger by calling the compute() method on the dask 
# dataframe. The execution of the line below takes a few seconds: 
>>> dfout = result.compute() 

# The result is a regular pandas dataframe: 
>>> type(dfout) 
<class 'pandas.core.frame.DataFrame'> 

# Of our 4 million records, only ~40k match the query: 
>>> len(dfout) 
41842 

>>> dfout.head() 
     CITY LANGUAGE GENRE count_GENRE count_LANGUAGE 
225 Mumbai English Action   2    3 
237 Mumbai English Action   3    2 
306 Mumbai English Action   3    3 
335 Mumbai English Action   2    2 
482 Mumbai English Action   2    3 

J'espère que cela vous permet de démarrer sur la solution à votre problème. Pour plus d'informations sur dask voir le tutorial et examples.

+0

@ Pedro-merci pour une nouvelle approche.Je n'ai pas encore testé votre exemple.Mais combien de temps (env.) Il a fallu pour filtrer à partir de 4 dossiers mln. – Satya

+0

@Satya 'Dans [6]:% temps dfout = result.compute() Temps de mur: 5.05 s' –

+1

@Satya,' dask' utilise en fait 'multiprocessing', donc vous verrez une accélération si vous en avez plus d'une core –