Je voudrais lire plusieurs fichiers csv d'un répertoire dans pandas et les concaténer dans un seul gros DataFrame. Je n'ai pas été capable de le comprendre cependant. Voici ce que j'ai jusqu'à présent:
import glob
import pandas as pd
# get data file names
path =r'C:\DRO\DCL_rawdata_files'
filenames = glob.glob(path + "/*.csv")
dfs = []
for filename in filenames:
dfs.append(pd.read_csv(filename))
# Concatenate all data into one DataFrame
big_frame = pd.concat(dfs, ignore_index=True)
Je suppose que j'ai besoin d'aide dans la boucle ???
Si vous avez les mêmes colonnes dans tous vos fichiers csv
, vous pouvez essayer le code ci-dessous. J'ai ajouté header=0
afin qu'après la lecture de csv
, la première ligne puisse être affectée comme nom de colonne.
import pandas as pd
import glob
path = r'C:\DRO\DCL_rawdata_files' # use your path
all_files = glob.glob(path + "/*.csv")
li = []
for filename in all_files:
df = pd.read_csv(filename, index_col=None, header=0)
li.append(df)
frame = pd.concat(li, axis=0, ignore_index=True)
Une alternative à réponse de darindaCoder :
path = r'C:\DRO\DCL_rawdata_files' # use your path
all_files = glob.glob(os.path.join(path, "*.csv")) # advisable to use os.path.join as this makes concatenation OS independent
df_from_each_file = (pd.read_csv(f) for f in all_files)
concatenated_df = pd.concat(df_from_each_file, ignore_index=True)
# doesn't create a list, nor does it append to one
import glob, os
df = pd.concat(map(pd.read_csv, glob.glob(os.path.join('', "my_files*.csv"))))
Presque toutes les réponses ici sont soit inutilement complexes (correspondance de modèle global), soit reposent sur des bibliothèques tierces supplémentaires. Vous pouvez le faire en 2 lignes en utilisant tout Pandas et python (toutes les versions) déjà intégrés.
Pour quelques dossiers - 1 liner:
df = pd.concat(map(pd.read_csv, ['data/d1.csv', 'data/d2.csv','data/d3.csv']))
Pour de nombreux fichiers:
from os import listdir
filepaths = [f for f in listdir("./data") if f.endswith('.csv')]
df = pd.concat(map(pd.read_csv, filepaths))
Cette ligne pandas qui définit le df utilise 3 choses:
pd.read_csv()
) l'itérable (notre liste) qui représente tous les éléments csv des chemins de fichiers).La bibliothèque Dask peut lire une image de données à partir de plusieurs fichiers:
>>> import dask.dataframe as dd
>>> df = dd.read_csv('data*.csv')
(Source: http://dask.pydata.org/en/latest/examples/dataframe-csv.html )
Les images Dask implémentent un sous-ensemble de l'API Pandas dataframe. Si toutes les données entrent dans la mémoire, vous pouvez appeler df.compute()
pour convertir le cadre de données en un cadre de données Pandas.
Edit: Je suis allé sur Google pour trouver mon chemin https://stackoverflow.com/a/21232849/186078 . Cependant, dernièrement, je trouve plus rapide de manipuler numpy avec une autre tâche, puis de l'attribuer une fois à dataframe plutôt que de manipuler celui-ci sur une base itérative, ce qui semble fonctionner également dans cette solution.
Je souhaite sincèrement que toute personne visitant cette page examine cette approche, mais je ne souhaite pas joindre cet énorme élément de code sous forme de commentaire afin de le rendre moins lisible.
Vous pouvez utiliser numpy pour accélérer réellement la concaténation de trames de données.
import os
import glob
import pandas as pd
import numpy as np
path = "my_dir_full_path"
allFiles = glob.glob(os.path.join(path,"*.csv"))
np_array_list = []
for file_ in allFiles:
df = pd.read_csv(file_,index_col=None, header=0)
np_array_list.append(df.as_matrix())
comb_np_array = np.vstack(np_array_list)
big_frame = pd.DataFrame(comb_np_array)
big_frame.columns = ["col1","col2"....]
Statistiques de chronométrage:
total files :192
avg lines per file :8492
--approach 1 without numpy -- 8.248656988143921 seconds ---
total records old :1630571
--approach 2 with numpy -- 2.289292573928833 seconds ---
Si vous voulez rechercher récursivement ( Python 3.5 ou supérieur ), vous pouvez procéder comme suit:
from glob import iglob
import pandas as pd
path = r'C:\user\your\path\**\*.csv'
all_rec = iglob(path, recursive=True)
dataframes = (pd.read_csv(f) for f in all_rec)
big_dataframe = pd.concat(dataframes, ignore_index=True)
Notez que les trois dernières lignes peuvent être exprimées en une ligne simple :
df = pd.concat((pd.read_csv(f) for f in iglob(path, recursive=True)), ignore_index=True)
Vous pouvez trouver la documentation de **
ici . De plus, j'ai utilisé iglob
au lieu de glob
, car il retourne un itérateur au lieu d'une liste.
EDIT: Fonction récursive multiplateforme:
Vous pouvez encapsuler ce qui précède dans une fonction multiplateforme (Linux, Windows, Mac), afin de pouvoir:
df = read_df_rec('C:\user\your\path', *.csv)
Voici la fonction:
from glob import iglob
from os.path import join
import pandas as pd
def read_df_rec(path, fn_regex=r'*.csv'):
return pd.concat((pd.read_csv(f) for f in iglob(
join(path, '**', fn_regex), recursive=True)), ignore_index=True)
Si plusieurs fichiers csv sont compressés, vous pouvez utiliser zipfile pour tout lire et concaténer comme ci-dessous:
import zipfile
import numpy as np
import pandas as pd
ziptrain = zipfile.ZipFile('yourpath/yourfile.Zip')
train=[]
for f in range(0,len(ziptrain.namelist())):
if (f == 0):
train = pd.read_csv(ziptrain.open(ziptrain.namelist()[f]))
else:
my_df = pd.read_csv(ziptrain.open(ziptrain.namelist()[f]))
train = (pd.DataFrame(np.concatenate((train,my_df),axis=0),
columns=list(my_df.columns.values)))
Basé sur la bonne réponse de @ Sid.
Avant de concaténer, vous pouvez charger les fichiers csv dans un dictionnaire intermédiaire qui donne accès à chaque ensemble de données en fonction du nom du fichier (sous la forme dict_of_df['filename.csv']
). Un tel dictionnaire peut vous aider à identifier les problèmes liés aux formats de données hétérogènes, par exemple lorsque les noms de colonne ne sont pas alignés.
import os
import glob
import pandas
from collections import OrderedDict
path =r'C:\DRO\DCL_rawdata_files'
filenames = glob.glob(path + "/*.csv")
Remarque: OrderedDict
n'est pas nécessaire, mais il conservera l'ordre des fichiers pouvant être utile à l'analyse.
dict_of_df = OrderedDict((f, pandas.read_csv(f)) for f in filenames)
pandas.concat(dict_of_df, sort=True)
Les clés sont des noms de fichier f
et les valeurs représentent le contenu des trames de données des fichiers csv. Au lieu d'utiliser f
comme clé de dictionnaire, vous pouvez également utiliser os.path.basename(f)
ou d'autres méthodes os.path pour réduire la taille de la clé dans le dictionnaire à la plus petite partie c'est pertinent.
une ligne utilisant map
, mais si vous souhaitez spécifier des arguments supplémentaires, vous pouvez procéder comme suit:
import pandas as pd
import glob
import functools
df = pd.concat(map(functools.partial(pd.read_csv, sep='|', compressed=None),
glob.glob("data/*.csv")))
Remarque: map
be ne vous permet pas de fournir des arguments supplémentaires.
Importez 2 ou plus de csv
sans avoir à dresser une liste de noms.
import glob
df = pd.concat(map(pd.read_csv, glob.glob('data/*.csv'))
J'ai trouvé cette méthode assez élégante.
import pandas as pd
import os
big_frame = pd.DataFrame()
for file in os.listdir():
if file.endswith('.csv'):
df = pd.read_csv(file)
big_frame = big_frame.append(df, ignore_index=True)
Un autre on-liner avec une compréhension de liste qui permet d'utiliser des arguments avec read_csv.
df = pd.concat([pd.read_csv(f'dir/{f}') for f in os.listdir('dir') if f.endswith('.csv')])