Chłopaki, mam tutaj 200 oddzielnych plików csv o nazwach od SH (1) do SH (200). Chcę połączyć je w jeden plik CSV. Jak mogę to zrobić?
python
csv
merge
concatenation
Gdakanie
źródło
źródło
Odpowiedzi:
Jak powiedział ghostdog74, ale tym razem z nagłówkami:
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()
źródło
f.__next__()
zamiast tego, jeślif.next()
w python3.x.with open
składni i uniknąć ręcznego.close()
wprowadzania plików.f.next()
if.__next__()
? kiedy używam tego pierwszego, otrzymałem'_io.TextIOWrapper' object has no attribute 'next'
fout.write(line)
to zrobię:if line[-1] != '\n': line += '\n'
Dlaczego nie możesz po prostu
sed 1d sh*.csv > merged.csv
?Czasami nie musisz nawet używać Pythona!
źródło
Użyj zaakceptowanej odpowiedzi StackOverflow, aby utworzyć listę plików CSV, które chcesz dołączyć, a następnie uruchom ten kod:
import pandas as pd combined_csv = pd.concat( [ pd.read_csv(f) for f in filenames ] )
A jeśli chcesz wyeksportować go do pojedynczego pliku csv, użyj tego:
combined_csv.to_csv( "combined_csv.csv", index=False )
źródło
fout=open("out.csv","a") for num in range(1,201): for line in open("sh"+str(num)+".csv"): fout.write(line) fout.close()
źródło
Przejdę tylko przez inny przykład kodu w koszyku
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)
źródło
To zależy, co masz na myśli, mówiąc „scalanie” - czy mają te same kolumny? Czy mają nagłówki? Na przykład, jeśli wszystkie mają te same kolumny i nie mają nagłówków, wystarczy prosta konkatenacja (otwórz plik docelowy do zapisu, pętla nad źródłami otwierającymi każde z nich do odczytu, użyj shutil.copyfileobj ze źródła open-for-reading do miejsce docelowe otwarte do zapisu, zamknij źródło, kontynuuj zapętlanie - użyj
with
instrukcji, aby wykonać zamknięcie w swoim imieniu). Jeśli mają te same kolumny, ale także nagłówki, będziesz potrzebować znakureadline
na każdym pliku źródłowym z wyjątkiem pierwszego, po otwarciu go do odczytu przed skopiowaniem do miejsca docelowego, aby pominąć wiersz nagłówków.Jeśli pliki CSV nie mają tych samych kolumn, musisz zdefiniować, w jakim sensie je „scalasz” (np. SQL JOIN? Lub „poziomo”, jeśli wszystkie mają tę samą liczbę wierszy? Itd.) ) - trudno nam zgadnąć, co masz na myśli w tym przypadku.
źródło
Niewielka zmiana w powyższym kodzie, ponieważ w rzeczywistości nie działa on poprawnie.
Powinno wyglądać następująco ...
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)
źródło
Jeśli scalony
glob
plik CSV ma być używany w Pythonie, po prostu użyj, aby uzyskać listę plików do przekazaniafileinput.input()
za pośrednictwemfiles
argumentu, a następnie użyjcsv
modułu, aby przeczytać wszystko za jednym razem.źródło
Całkiem łatwo połączyć wszystkie pliki w katalogu i scalić je
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)
źródło
Jeśli pracujesz na Linuksie / Macu, możesz to zrobić.
from subprocess import call script="cat *.csv>merge.csv" call(script,shell=True)
źródło
LUB, możesz po prostu zrobić
źródło
Możesz zaimportować csv, a następnie przejrzeć wszystkie pliki CSV i odczytać je na liście. Następnie zapisz listę z powrotem na dysk.
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))
Powyższe nie jest bardzo niezawodne, ponieważ nie obsługuje błędów ani nie zamyka żadnych otwartych plików. Powinno to działać niezależnie od tego, czy poszczególne pliki mają jeden lub więcej wierszy danych CSV. Nie uruchomiłem również tego kodu, ale powinien dać ci pomysł, co robić.
źródło
W przypadku rozwiązania, które sprawiło, że @Adders i później zostało ulepszone przez @varun, zaimplementowałem trochę ulepszeń, pozostawiając cały scalony plik CSV tylko z głównym nagłówkiem:
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()
Z poważaniem!!!
źródło
Możesz po prostu skorzystać z wbudowanej
csv
biblioteki. To rozwiązanie zadziała, nawet jeśli niektóre z Twoich plików CSV mają nieco inne nazwy kolumn lub nagłówki, w przeciwieństwie do innych odpowiedzi najczęściej wybieranych.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)
Scalony plik będzie zawierał wszystkie możliwe kolumny (
header_keys
), które można znaleźć w plikach. Wszelkie brakujące kolumny w pliku byłyby renderowane jako puste / puste (ale z zachowaniem reszty danych pliku).Uwaga:
csv
biblioteki, ale zamiast używaćDictReader
&DictWriter
, będziesz musiał pracować z podstawowymreader
&writer
.merged_rows
lista).źródło
Zmodyfikowałem to, co @wisty powiedział, że działa z pythonem 3.x, dla tych z Was, którzy mają problem z kodowaniem, również używam modułu os, aby uniknąć twardego kodowania
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()
źródło
Oto skrypt:
SH1.csv
doSH200.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())
źródło
Aktualizuję odpowiedź Wisty dla Pythona3
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()
źródło
Powiedzmy, że masz 2
csv
takie pliki:csv1.csv:
id,name 1,Armin 2,Sven
csv2.csv:
id,place,year 1,Reykjavik,2017 2,Amsterdam,2018 3,Berlin,2019
i chcesz, aby wynik był taki jak ten csv3.csv:
id,name,place,year 1,Armin,Reykjavik,2017 2,Sven,Amsterdam,2018 3,,Berlin,2019
W tym celu możesz użyć następującego fragmentu kodu:
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)
Za pomocą pętli możesz osiągnąć ten sam wynik dla wielu plików, jak w twoim przypadku (200 plików csv).
źródło
Jeśli pliki nie są ponumerowane w kolejności, zastosuj bezproblemowe podejście poniżej: Python 3.6 na komputerze z systemem Windows:
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)
źródło
Łatwa w użyciu funkcja:
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)
źródło
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()
źródło