web-dev-qa-db-fra.com

comment fusionner 200 fichiers csv en Python

Les gars, j'ai ici 200 fichiers csv distincts nommés de SH (1) à SH (200). Je veux les fusionner en un seul fichier csv. Comment puis-je le faire?

56
Chuck

Comme dit ghostdog74, mais cette fois avec des en-têtes:

fout=open("out.csv","a")
# first file:
for line in open("sh1.csv"):
    fout.write(line)
# now the rest:    
for num in range(2,201):
    f = open("sh"+str(num)+".csv")
    f.next() # skip the header
    for line in f:
         fout.write(line)
    f.close() # not really needed
fout.close()
72
wisty

Pourquoi ne peux-tu pas juste sed 1d sh*.csv > merged.csv?

Parfois, vous n'avez même pas besoin d'utiliser python!

38
blinsay

Utilisez acceptés StackOverflow answer pour créer une liste des fichiers csv que vous souhaitez ajouter, puis exécutez ce code:

import pandas as pd
combined_csv = pd.concat( [ pd.read_csv(f) for f in filenames ] )

Et si vous voulez l'exporter dans un seul fichier csv, utilisez ceci:

combined_csv.to_csv( "combined_csv.csv", index=False )
28
scottlittle
fout=open("out.csv","a")
for num in range(1,201):
    for line in open("sh"+str(num)+".csv"):
         fout.write(line)    
fout.close()
15
ghostdog74

Je vais juste à travers un autre exemple de code dans le panier

from glob import glob

with open('singleDataFile.csv', 'a') as singleFile:
    for csvFile in glob('*.csv'):
        for line in open(csvFile, 'r'):
            singleFile.write(line)
11
Norfeldt

Cela dépend de ce que vous entendez par "fusionner" - ont-ils les mêmes colonnes? Ont-ils des en-têtes? Par exemple, si elles ont toutes les mêmes colonnes et sans en-tête, une simple concaténation est suffisante (ouvrez le fichier de destination en écriture, passez en boucle sur les sources ouvrant chacune en lecture, utilisez shutil.copyfileobj à partir de lecture de la source dans la destination ouverte à l'écriture, fermeture de la source, boucle persistante - utilisez l'instruction with pour effectuer la fermeture en votre nom). S'ils ont les mêmes colonnes, mais aussi les en-têtes, vous aurez besoin d'une readline sur chaque fichier source sauf le premier, après l'avoir ouvert pour le lire avant de le copier dans la destination, pour ignorer la ligne des en-têtes.

Si les fichiers CSV ne possèdent pas tous les mêmes colonnes, vous devez définir dans quel sens vous les "fusionnez" (comme un SQL JOIN? Ou "horizontalement" s'ils ont tous le même nombre de lignes? Etc, etc. ) - il est difficile pour nous de deviner ce que vous voulez dire dans ce cas.

10
Alex Martelli

Si le fichier CSV fusionné doit être utilisé en Python, utilisez simplement glob pour obtenir une liste des fichiers à transmettre à fileinput.input() via l'argument files, puis utilisez le module csv pour lire. tout en un.

3

Une légère modification du code ci-dessus car il ne fonctionne pas correctement.

Ce devrait être comme suit ...

from glob import glob

with open('main.csv', 'a') as singleFile:
    for csv in glob('*.csv'):
        if csv == 'main.csv':
            pass
        else:
            for line in open(csv, 'r'):
                singleFile.write(line)
3
Adders

Il est très facile de combiner tous les fichiers d'un répertoire et de les fusionner

import glob
import csv


# Open result file
with open('output.txt','wb') as fout:
    wout = csv.writer(fout,delimiter=',') 
    interesting_files = glob.glob("*.csv") 
    h = True
    for filename in interesting_files: 
        print 'Processing',filename 
        # Open and process file
        with open(filename,'rb') as fin:
            if h:
                h = False
            else:
                fin.next()#skip header
            for line in csv.reader(fin,delimiter=','):
                wout.writerow(line)
2
varun

Vous pouvez importer csv puis parcourir tous les fichiers CSV en les lisant dans une liste. Puis écrivez la liste sur le disque.

import csv

rows = []

for f in (file1, file2, ...):
    reader = csv.reader(open("f", "rb"))

    for row in reader:
        rows.append(row)

writer = csv.writer(open("some.csv", "wb"))
writer.writerows("\n".join(rows))

Ce qui précède n’est pas très robuste, car il ne gère pas les erreurs et ne ferme pas les fichiers ouverts . Cela devrait fonctionner, que les fichiers individuels contiennent une ou plusieurs lignes de données CSV. De plus, je n'ai pas exécuté ce code, mais il devrait vous donner une idée de ce qu'il faut faire.

1
cnobile

Si vous travaillez sur linux/mac, vous pouvez le faire.

from subprocess import call
script="cat *.csv>merge.csv"
call(script,Shell=True)
1
sunny

Mise à jour de la réponse de Wisty pour python3

fout=open("out.csv","a")
# first file:
for line in open("sh1.csv"):
    fout.write(line)
# now the rest:    
for num in range(2,201):
    f = open("sh"+str(num)+".csv")
    next(f) # skip the header
    for line in f:
         fout.write(line)
    f.close() # not really needed
fout.close()
0
ishandutta2007

Voici un script:

  • Concaténation de fichiers csv nommés SH1.csv à SH200.csv
  • Garder les en-têtes
import glob
import re

# Looking for filenames like 'SH1.csv' ... 'SH200.csv'
pattern = re.compile("^SH([1-9]|[1-9][0-9]|1[0-9][0-9]|200).csv$")
file_parts = [name for name in glob.glob('*.csv') if pattern.match(name)]

with open("file_merged.csv","wb") as file_merged:
    for (i, name) in enumerate(file_parts):
        with open(name, "rb") as file_part:
            if i != 0:
                next(file_part) # skip headers if not first file
            file_merged.write(file_part.read())
0
x0s

OU vous pouvez simplement faire

cat sh*.csv > merged.csv
0
Nanashi No Gombe

J'ai modifié ce que @wisty disait être utilisé avec python 3.x, pour ceux d'entre vous qui ont un problème d'encodage, j'utilise aussi os module pour éviter le codage dur

import os 
def merge_all():
    dir = os.chdir('C:\python\data\\')
    fout = open("merged_files.csv", "ab")
    # first file:
    for line in open("file_1.csv",'rb'):
        fout.write(line)
    # now the rest:
    list = os.listdir(dir)
    number_files = len(list)
    for num in range(2, number_files):
        f = open("file_" + str(num) + ".csv", 'rb')
        f.__next__()  # skip the header
        for line in f:
            fout.write(line)
        f.close()  # not really needed
    fout.close()
0
Maryam Pashmi

Si les fichiers ne sont pas numérotés dans l’ordre, suivez l’approche ci-après sans problème:

import pandas as pd
from glob import glob

interesting_files = glob("C:/temp/*.csv") # it grabs all the csv files from the directory you mention here

df_list = []
for filename in sorted(interesting_files):

df_list.append(pd.read_csv(filename))
full_df = pd.concat(df_list)

# save the final file in same/different directory:
full_df.to_csv("C:/temp/merged_pandas.csv", index=False)
0
Azadeh Feizpour

Disons que vous avez 2 fichiers csv comme ceux-ci: 

csv1.csv: 

id,name
1,Armin
2,Sven

csv2.csv:

id,place,year
1,Reykjavik,2017
2,Amsterdam,2018
3,Berlin,2019

et vous voulez que le résultat soit comme ceci csv3.csv:

id,name,place,year
1,Armin,Reykjavik,2017
2,Sven,Amsterdam,2018
3,,Berlin,2019

Ensuite, vous pouvez utiliser l'extrait suivant pour le faire:

import csv
import pandas as pd

# the file names
f1 = "csv1.csv"
f2 = "csv2.csv"
out_f = "csv3.csv"

# read the files
df1 = pd.read_csv(f1)
df2 = pd.read_csv(f2)

# get the keys
keys1 = list(df1)
keys2 = list(df2)

# merge both files
for idx, row in df2.iterrows():
    data = df1[df1['id'] == row['id']]

    # if row with such id does not exist, add the whole row
    if data.empty:
        next_idx = len(df1)
        for key in keys2:
            df1.at[next_idx, key] = df2.at[idx, key]

    # if row with such id exists, add only the missing keys with their values
    else:
        i = int(data.index[0])
        for key in keys2:
            if key not in keys1:
                df1.at[i, key] = df2.at[idx, key]

# save the merged files
df1.to_csv(out_f, index=False, encoding='utf-8', quotechar="", quoting=csv.QUOTE_NONE)

Avec l'aide d'une boucle, vous pouvez obtenir le même résultat pour plusieurs fichiers que dans votre cas (200 fichiers CSV).

0
tsveti_iko