web-dev-qa-db-fra.com

python - Utilisation de pandas structures avec un grand csv (itération et taille de bloc)

J'ai un gros fichier csv, environ 600 Mo avec 11 millions de lignes et je veux créer des données statistiques comme des pivots, des histogrammes, des graphiques, etc. En essayant évidemment de simplement le lire normalement:

df = pd.read_csv('Check400_900.csv', sep='\t')

ne fonctionne pas, donc j'ai trouvé itérer et chunksize dans un poste similaire, donc j'ai utilisé

df = pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000)

Très bien, je peux par exemple print df.get_chunk(5) et rechercher tout le fichier avec juste

for chunk in df:
    print chunk

Mon problème est que je ne sais pas comment utiliser des trucs comme ceux-ci ci-dessous pour l'ensemble du df et pas pour un seul morceau

plt.plot()
print df.head()
print df.describe()
print df.dtypes
customer_group3 = df.groupby('UserID')
y3 = customer_group.size()

J'espère que ma question n'est pas si confuse

22
Thodoris P

Solution, si besoin, créez un grand DataFrame si besoin traite toutes les données à la fois (ce qui est possible, mais pas recommandé ):

Ensuite, utilisez concat pour tous les morceaux à df, car le type de sortie de la fonction:

df = pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000)

n'est pas une trame de données, mais pandas.io.parsers.TextFileReader - source .

tp = pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000)
print tp
#<pandas.io.parsers.TextFileReader object at 0x00000000150E0048>
df = pd.concat(tp, ignore_index=True)

Je pense qu'il est nécessaire d'ajouter le paramètre ignorer l'index à la fonction concat, car en évitant la duplicité des index.

MODIFIER:

Mais si vous voulez travailler avec des données volumineuses comme l'agrégation, il vaut mieux utiliser dask , car il offre un parallélisme avancé.

22
jezrael

Vous avez pas besoin de concat ici. C'est exactement comme écrire sum(map(list, grouper(tup, 1000))) au lieu de list(tup). La seule chose iterator et chunksize=1000 fait est de vous donner un objet lecteur qui itère les DataFrames à 1000 lignes au lieu de lire le tout. Si vous voulez tout à la fois, n'utilisez pas ces paramètres.

Mais si la lecture de l'ensemble du fichier en mémoire à la fois est trop chère (p. Ex., Prend tellement de mémoire que vous obtenez un MemoryError, ou ralentissez votre système à une analyse en le jetant dans l'enfer de swap), c'est exactement ce que chunksize est pour.

Le problème est que vous avez nommé l'itérateur résultant df, puis avez essayé de l'utiliser comme DataFrame. Ce n'est pas un DataFrame; c'est un itérateur qui vous donne un à un des DataFrames à 1000 lignes.

Quand tu dis ça:

Mon problème est que je ne sais pas comment utiliser des trucs comme ceux-ci ci-dessous pour l'ensemble du df et pas pour un seul morceau

La réponse est que vous ne pouvez pas. Si vous ne pouvez pas charger le tout dans un DataFrame géant, vous ne pouvez pas utiliser un DataFrame géant. Vous devez réécrire votre code autour de morceaux.

Au lieu de cela:

df = pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000)
print df.dtypes
customer_group3 = df.groupby('UserID')

… Vous devez faire des choses comme ça:

for df in pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000):
    print df.dtypes
    customer_group3 = df.groupby('UserID')

Souvent, ce que vous devez faire est d'agréger certaines données - réduisez chaque bloc à quelque chose de beaucoup plus petit avec uniquement les pièces dont vous avez besoin. Par exemple, si vous souhaitez additionner le fichier entier par groupes, vous pouvez groupby chaque bloc, puis additionner le bloc par groupes et stocker une série/tableau/liste/dict de totaux en cours d'exécution pour chaque groupe.

Bien sûr, c'est un peu plus compliqué que de simplement résumer une série géante à la fois, mais il n'y a aucun moyen de contourner cela. (Sauf pour acheter plus RAM et/ou passer à 64 bits.) C'est ainsi que iterator et chunksize résolvent le problème: en vous permettant de faire ce compromis quand vous en avez besoin.

8
abarnert

Vous devez concaténer les mandrins. Par exemple:

df2 = pd.concat([chunk for chunk in df])

Et puis exécutez vos commandes sur df2

4
user29791