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?
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()
Pourquoi ne peux-tu pas juste sed 1d sh*.csv > merged.csv
?
Parfois, vous n'avez même pas besoin d'utiliser python!
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 )
fout=open("out.csv","a")
for num in range(1,201):
for line in open("sh"+str(num)+".csv"):
fout.write(line)
fout.close()
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)
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.
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.
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)
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)
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.
Si vous travaillez sur linux/mac, vous pouvez le faire.
from subprocess import call
script="cat *.csv>merge.csv"
call(script,Shell=True)
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()
Voici un script:
SH1.csv
à SH200.csv
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())
OU vous pouvez simplement faire
cat sh*.csv > merged.csv
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()
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)
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).