So führen Sie 200 CSV-Dateien in Python zusammen

82

Leute, ich habe hier 200 separate CSV-Dateien mit den Namen SH (1) bis SH (200). Ich möchte sie in einer einzigen CSV-Datei zusammenführen. Wie kann ich es tun?

Futter
quelle
3
Auf welche Weise würden Sie sie zusammenführen? (Verkettete Zeilen, ...)
am
6
Wie sollen sie zusammengeführt werden? Jede Zeile in einer CSV-Datei ist eine Zeile. Eine einfache Möglichkeit besteht darin, alle Dateien miteinander zu verknüpfen.
Jon-Eric
Jede Datei hat zwei Spalten. Ich möchte sie in einer einzigen Datei mit zwei aufeinanderfolgenden Spalten zusammenführen.
Chuck
1
@Chuck: Wie wäre es, wenn Sie alle Antworten in Ihren Kommentaren (auf die Frage und auf die Antworten) nehmen und Ihre Frage aktualisieren würden?
tumultous_rooster
1
Diese Frage sollte "How to concat ..." anstelle von "how to merge ..."
heißen

Antworten:

92

Wie Ghostdog74 sagte, aber diesmal mit Headern:

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()
wehmütig
quelle
11
Sie können f.__next__()stattdessen f.next()in python3.x verwenden.
Tsveti_iko
5
Nur eine Anmerkung: Man kann die with openSyntax verwenden und vermeiden, .close()die Dateien manuell zu bearbeiten.
FatihAkici
2
Was ist der Unterschied zwischen f.next()und f.__next__()? Wenn ich das erstere benutze, habe ich'_io.TextIOWrapper' object has no attribute 'next'
Jason Goal
bevor fout.write(line)ich tun würde:if line[-1] != '\n': line += '\n'
Shisui
64

Warum kannst du nicht einfach sed 1d sh*.csv > merged.csv?

Manchmal muss man nicht einmal Python verwenden!

blinsay
quelle
21
Unter Windows C: \> Kopie * .csv Merged.csv
Luftangriff
5
Kopieren Sie die Header-Informationen aus einer Datei: sed -n 1p some_file.csv> fusioned_file.csv Kopieren Sie alle bis auf die letzte Zeile aus allen anderen Dateien: sed 1d * .csv >> fusioned_file.csv
siehe
3
@blinsay Der Header in jeder CSV-Datei wird jedoch auch zur zusammengeführten Datei hinzugefügt.
Mina
5
Wie können Sie diesen Befehl verwenden, ohne die Header-Informationen für jede nachfolgende Datei nach der ersten zu kopieren? Ich scheine die Header-Informationen immer wieder auftauchen zu lassen.
Joe
2
Dies ist großartig, wenn Sie den Header nicht entfernen müssen!
Blairg23
50

Verwenden Sie die akzeptierte StackOverflow-Antwort , um eine Liste der CSV-Dateien zu erstellen, die Sie anhängen möchten, und führen Sie dann diesen Code aus:

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

Und wenn Sie es in eine einzelne CSV-Datei exportieren möchten, verwenden Sie Folgendes:

combined_csv.to_csv( "combined_csv.csv", index=False )
scottlittle
quelle
@ wisty, @ Andy, angenommen, alle Dateien haben Titel für jede Zeile - einige Zeilen mit unterschiedlichen Titeln. Keine Überschriften für die 2 Spalten in jeder Datei. Wie kann man zusammenführen, so dass für jede Datei nur eine Spalte hinzugefügt wird.
Gathide
Wohin wird die Datei exportiert?
@ Dirtysocks45, ich habe die Antwort geändert, um dies deutlicher zu machen.
Scottlittle
add sort: kombiniert_csv = pd.concat ([pd.read_csv (f) für f in Dateinamen], sort = False)
Segelfisch009
16
fout=open("out.csv","a")
for num in range(1,201):
    for line in open("sh"+str(num)+".csv"):
         fout.write(line)    
fout.close()
Ghostdog74
quelle
12

Ich werde nur ein weiteres Codebeispiel im Warenkorb durchgehen

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)
Norfeldt
quelle
2
@Andy Ich sehe keinen Unterschied zwischen einem Stapelüberlauf, der mich daran erinnert, eine Antwort abzustimmen, und einem, der die Leute daran erinnert, ihre Wertschätzung zu teilen (indem sie abstimmen), wenn sie meine Antwort nützlich fanden. Ich weiß, dass dies nicht Facebook ist und ich kein Like-Jäger bin.
Norfeldt
1
Es wurde bereits zuvor diskutiert und jedes Mal als inakzeptabel eingestuft.
Andy
10

Es kommt darauf an, was Sie unter "Zusammenführen" verstehen - haben sie dieselben Spalten? Haben sie Header? Wenn sie beispielsweise alle die gleichen Spalten und keine Header haben, ist eine einfache Verkettung ausreichend (öffnen Sie die Zieldatei zum Schreiben, durchlaufen Sie die Quellen, die jeweils zum Lesen geöffnet sind , und verwenden Sie shutil.copyfileobj von der Quelle zum Lesen zum Öffnen in die Ziel zum Schreiben öffnen, Quelle schließen, Schleife fortsetzen - Verwenden Sie die withAnweisung, um das Schließen in Ihrem Namen durchzuführen. Wenn sie dieselben Spalten, aber auch Überschriften haben, benötigen Sie readlinefür jede Quelldatei eine, mit Ausnahme der ersten, nachdem Sie sie zum Lesen geöffnet haben, bevor Sie sie in das Ziel kopieren, um die Überschriftenzeile zu überspringen.

Wenn die CSV-Dateien nicht alle die gleichen Spalten haben, müssen Sie definieren, in welchem ​​Sinne Sie sie "zusammenführen" (wie ein SQL JOIN? Oder "horizontal", wenn sie alle die gleiche Anzahl von Zeilen haben? Etc usw. ) - Es fällt uns schwer zu erraten, was Sie in diesem Fall meinen.

Alex Martelli
quelle
Jede Datei hat zwei Spalten mit Überschriften. Ich möchte sie in einer einzigen Datei mit zwei aufeinanderfolgenden Spalten zusammenführen.
Chuck
3

Wenn die zusammengeführte CSV in Python verwendet werden soll, verwenden Sie einfach glob, um eine Liste der Dateien abzurufen, an die fileinput.input()über das filesArgument übergeben werden soll, und verwenden Sie dann das csvModul, um alles auf einmal zu lesen.

Ignacio Vazquez-Abrams
quelle
3

Eine geringfügige Änderung des obigen Codes, da er nicht richtig funktioniert.

Es sollte wie folgt sein ...

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)
Addierer
quelle
3

Ganz einfach, alle Dateien in einem Verzeichnis zu kombinieren und zusammenzuführen

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)
varun
quelle
3

Wenn Sie unter Linux / Mac arbeiten, können Sie dies tun.

from subprocess import call
script="cat *.csv>merge.csv"
call(script,shell=True)
sonnig
quelle
2

ODER du könntest es einfach tun

cat sh*.csv > merged.csv
Nanashi No Gombe
quelle
1

Sie können CSV importieren und dann alle CSV-Dateien, die sie lesen, in einer Liste durchlaufen. Schreiben Sie dann die Liste wieder auf die Festplatte.

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))

Das Obige ist nicht sehr robust, da es weder eine Fehlerbehandlung aufweist noch offene Dateien schließt. Dies sollte funktionieren, unabhängig davon, ob die einzelnen Dateien eine oder mehrere Zeilen mit CSV-Daten enthalten. Ich habe diesen Code auch nicht ausgeführt, aber er sollte Ihnen eine Vorstellung davon geben, was zu tun ist.

cnobile
quelle
1

Über die Lösung, die @Adders gemacht und später von @varun verbessert hat, habe ich auch einige kleine Verbesserungen implementiert, sodass die gesamte zusammengeführte CSV nur den Hauptheader enthält:

from glob import glob

filename = 'main.csv'

with open(filename, 'a') as singleFile:
    first_csv = True
    for csv in glob('*.csv'):
        if csv == filename:
            pass
        else:
            header = True
            for line in open(csv, 'r'):
                if first_csv and header:
                    singleFile.write(line)
                    first_csv = False
                    header = False
                elif header:
                    header = False
                else:
                    singleFile.write(line)
    singleFile.close()

Freundliche Grüße!!!

Fabián Miranda Muñoz
quelle
1

Sie können einfach die eingebaute csvBibliothek verwenden. Diese Lösung funktioniert auch dann, wenn einige Ihrer CSV-Dateien im Gegensatz zu den anderen Antworten mit den höchsten Stimmen leicht unterschiedliche Spaltennamen oder Überschriften haben.

import csv
import glob


filenames = [i for i in glob.glob("SH*.csv")]
header_keys = []
merged_rows = []

for filename in filenames:
    with open(filename) as f:
        reader = csv.DictReader(f)
        merged_rows.extend(list(reader))
        header_keys.extend([key for key in reader.fieldnames if key not in header_keys])

with open("combined.csv", "w") as f:
    w = csv.DictWriter(f, fieldnames=header_keys)
    w.writeheader()
    w.writerows(merged_rows)

Die zusammengeführte Datei enthält alle möglichen Spalten ( header_keys), die in den Dateien gefunden werden können. Alle fehlenden Spalten in einer Datei werden als leer / leer gerendert (wobei die restlichen Daten der Datei erhalten bleiben).

Hinweis:

  • Dies funktioniert nicht, wenn Ihre CSV-Dateien keine Header haben. In diesem Fall können Sie die csvBibliothek weiterhin verwenden , aber anstatt DictReader& zu verwenden DictWriter, müssen Sie mit dem grundlegenden reader& arbeiten writer.
  • Dies kann zu Problemen führen, wenn Sie mit massiven Daten arbeiten, da der gesamte Inhalt im Speicher ( merged_rowsListe) gespeichert wird .
shad0w_wa1k3r
quelle
0

Ich habe geändert, was @wisty gesagt hat, um mit Python 3.x zu arbeiten. Für diejenigen unter Ihnen, die Codierungsprobleme haben, verwende ich auch das OS-Modul, um eine harte Codierung zu vermeiden

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()
Maryam Pashmi
quelle
0

Hier ist ein Skript:

  • Verkettung von CSV-Dateien mit dem Namen SH1.csv zuSH200.csv
  • Die Überschriften behalten
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())
x0s
quelle
0

Wistys Antwort für Python3 wird aktualisiert

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()
ishandutta2007
quelle
0

Angenommen, Sie haben 2 csv Dateien wie diese:

csv1.csv:

id,name
1,Armin
2,Sven

csv2.csv:

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

und Sie möchten, dass das Ergebnis wie folgt aussieht: csv3.csv:

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

Dann können Sie das folgende Snippet verwenden, um dies zu tun:

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)

Mit Hilfe einer Schleife können Sie für mehrere Dateien das gleiche Ergebnis erzielen wie in Ihrem Fall (200 CSV-Dateien).

tsveti_iko
quelle
0

Wenn die Dateien nicht in der richtigen Reihenfolge nummeriert sind, gehen Sie wie folgt vor: Python 3.6 auf Windows-Computern:

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)
Azadeh Feizpour
quelle
0

Eine einfach zu bedienende Funktion:

def csv_merge(destination_path, *source_paths):
'''
Merges all csv files on source_paths to destination_path.
:param destination_path: Path of a single csv file, doesn't need to exist
:param source_paths: Paths of csv files to be merged into, needs to exist
:return: None
'''
with open(destination_path,"a") as dest_file:
    with open(source_paths[0]) as src_file:
        for src_line in src_file.read():
            dest_file.write(src_line)
    source_paths.pop(0)
    for i in range(len(source_paths)):
        with open(source_paths[i]) as src_file:
            src_file.next()
            for src_line in src_file:
                 dest_file.write(src_line)
Ken Shibata
quelle
0
import pandas as pd
import os

df = pd.read_csv("e:\\data science\\kaggle assign\\monthly sales\\Pandas-Data-Science-Tasks-master\\SalesAnalysis\\Sales_Data\\Sales_April_2019.csv")
files = [file for file in  os.listdir("e:\\data science\\kaggle assign\\monthly sales\\Pandas-Data-Science-Tasks-master\\SalesAnalysis\\Sales_Data")
for file in files:
    print(file)

all_data = pd.DataFrame()
for file in files:
    df=pd.read_csv("e:\\data science\\kaggle assign\\monthly sales\\Pandas-Data-Science-Tasks-master\\SalesAnalysis\\Sales_Data\\"+file)
    all_data = pd.concat([all_data,df])
    all_data.head()
Sunit Deogam
quelle