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ć?
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ć?
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()
f.__next__()
zamiast tego, jeśli f.next()
w python3.x.
with open
składni i uniknąć ręcznego .close()
wprowadzania plików.
f.next()
i f.__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!
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 )
fout=open("out.csv","a")
for num in range(1,201):
for line in open("sh"+str(num)+".csv"):
fout.write(line)
fout.close()
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)
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ć znaku readline
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.
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)
Jeśli scalony glob
plik CSV ma być używany w Pythonie, po prostu użyj, aby uzyskać listę plików do przekazania fileinput.input()
za pośrednictwem files
argumentu, a następnie użyj csv
modułu, aby przeczytać wszystko za jednym razem.
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)
LUB, możesz po prostu zrobić
cat sh*.csv > merged.csv
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ć.
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!!!
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 podstawowym reader
& writer
.merged_rows
lista).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()
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())
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()
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).
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)
Ł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)
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()