2017-10-10 5 views
0

J'essaie de créer une base de données ayant deux colonnes à partir de 50 fichiers CSV ayant 5000 lignes et environ 15 colonnes. Lorsque j'essaie de l'exécuter sans utiliser la fonction de concaténation, j'utilise beaucoup de mémoire et j'ai l'erreur kill. Maintenant, je suis en train de décomposer la base de données, puis de concéder la même chose. Le seul problème est que quand je concat les morceaux, il garde l'en-tête pour chaque morceau et quand j'imprime head() pour la df, il me fournit les rangées de têtes du dernier morceau. Et y a-t-il un autre moyen de faire fonctionner mon code encore plus rapidement, comme je l'ai lu en utilisant la fonction de concat dans la boucle pour la rendre plus lente. Mon code va comme ceci: -Gestion de gros fichiers CSV dans Python3 à l'aide de la fonction de concatation

import os 
import csv 
import urllib.request as urllib 
import datetime as dt 
import pandas as pd 
import pandas_datareader.data as web 
import nsepy as nse 

def saveNiftySymbols(): 
    url = "https://www.nseindia.com/content/indices/ind_nifty50list.csv" 
# pretend to be a chrome 47 browser on a windows 10 machine 
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"} 
    req = urllib.Request(url, headers = headers) 
# open the url 
    x = urllib.urlopen(req) 
    sourceCode = x.read().decode('utf-8') 

    cr = csv.DictReader(sourceCode.splitlines()) 
    l = [row['Symbol'] for row in cr] 
    return l 

def symbolToPath(symbol, path='/Users/uditvashisht/Documents/udi_py/stocks/stock_dfs/'): 
    return os.path.join(path,"{}.csv".format(str(symbol))) 

def combinedNifty(l): 
    mainDf=pd.DataFrame() 

    for symbol in l: 
     chunks=pd.read_csv(symbolToPath(symbol),chunksize=10,usecols=['Date','Close'],index_col='Date',parse_dates=True) 
     df=pd.DataFrame() 
     for chunk in chunks: 
      df=pd.concat([chunk]) 

      df.rename(columns={'Close':symbol}, inplace=True) 


     if mainDf.empty: 
      mainDf = df 
     else: 
      mainDf = mainDf.join(df, how='outer') 

    print(mainDf.head()) 
    mainDf.to_csv('combinedNifty.csv') 


combinedNifty(saveNiftySymbols()) 

Répondre

0

Le seul problème est que lorsque je concat les morceaux, il garde l'en-tête pour chaque morceau et quand je la tête d'impression() pour la df, il me donne la lignes de tête ne dernier morceau

C'est parce que ce qui se passe réellement est que vous avez seulement le dernier morceau dans votre df. Lorsque vous exécutez cette ligne:

df=pd.concat([chunk]) 

Vous redéfinissez effectivement df par concaténer seulement votre morceau en cours avec rien d'autre. Il est efficace comme si vous faisiez:

For chunk in chunks: 
    df = chunk 

C'est pourquoi lorsque vous appelez la méthode que vous voyez que la tête() que le dernier morceau. Au lieu de cela, vous n'avez pas besoin d'une boucle for pour concaténer les morceaux. Concat prend une liste de dataframes que l'argument et les concaténer ensemble, de sorte que vous ne devez faire:

df = pd.concat(chunks) 

Cela devrait également améliorer les performances, car il est préférable de concaténer une fois avec une liste de plusieurs dataframes au lieu de faire quelque chose comme df = pd.concat ([df, chunk]) dans une boucle for, ce qui est probablement ce que vous vouliez faire dans votre code original.

+0

Salut, j'ai utilisé votre méthode, cela m'a aidé à obtenir le cadre de données complet pour un symbole individuel dans la liste, au lieu de morceaux. Mais encore si je l'utilise avec le code ci-dessus pour créer des données à partir de 50 fichiers CSV, puis de les rejoindre. Je suis victime d'une erreur: 9. –

+0

Essayez l'approche donnée [ici] (https://stackoverflow.com/questions/38089010/merge-a-list-of-pandas-dataframes) pour utiliser 'pd.merge' au lieu de rejoindre afin de fusionner toutes vos données en une fois à l'extérieur de la boucle for au lieu d'appeler df.join à plusieurs reprises. Je ne suis pas sûr si join a le même problème que concat, mais pourrait améliorer les choses. Faites une liste vide et ajoutez votre 'df' à cette liste sur chaque' pour le symbole dans l: 'loop, puis fusionnez à la fin. Vérifiez également [cette méthode] (https://stackoverflow.com/questions/17557074/memory-error-when-using-pandas-read-csv) pour réduire les erreurs de mémoire lors de la lecture de csv. –

+0

Aussi, je ne suis pas sûr pourquoi vous utilisez de telles petites tailles de morceaux pour traiter le csv. Voir [ce post] (https://stackoverflow.com/questions/25962114/how-to-read-a-6-gb-csv-file-with-pandas) sur le traitement de gros csv avec des morceaux. Les commentaires décrivent également l'avantage d'appeler concat sur une liste plutôt qu'avec une boucle for. –