Хлопці, у мене тут є 200 окремих файлів csv з іменами від SH (1) до SH (200). Я хочу об'єднати їх в один файл CSV. Як я можу це зробити?
Хлопці, у мене тут є 200 окремих файлів csv з іменами від SH (1) до SH (200). Я хочу об'єднати їх в один файл CSV. Як я можу це зробити?
Відповіді:
Як сказав ghostdog74, але цього разу із заголовками:
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__()
замість цього, якщо f.next()
в python3.x.
with open
синтаксис і уникати вручну .close()
введення файлів.
f.next()
та f.__next__()
? коли я використовую перше, я отримав'_io.TextIOWrapper' object has no attribute 'next'
fout.write(line)
я б це зробив:if line[-1] != '\n': line += '\n'
Чому ви не можете просто sed 1d sh*.csv > merged.csv
?
Іноді навіть не потрібно використовувати python!
Використовуйте прийняту відповідь StackOverflow, щоб створити список файлів csv, які потрібно додати, а потім запустіть цей код:
import pandas as pd
combined_csv = pd.concat( [ pd.read_csv(f) for f in filenames ] )
І якщо ви хочете експортувати його в один файл csv, використовуйте це:
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()
Я просто перегляну ще один приклад коду в кошику
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)
Це залежить від того, що ви маєте на увазі під «злиттям» - чи мають вони однакові стовпці? У них є заголовки? Наприклад, якщо всі вони мають однакові стовпці, а заголовків немає, достатньо простої конкатенації (відкрийте цільовий файл для запису, прокрутіть джерела, що відкриваються для читання, використовуйте shutil.copyfileobj з джерела відкритого для читання в відкрите для написання місце, закрийте джерело, продовжуйте цикл - використовуйте with
заяву, щоб зробити закриття від вашого імені). Якщо вони мають однакові стовпці, але також заголовки, вам знадобиться readline
файл кожного вихідного файлу, крім першого, після того, як ви відкриєте його для читання, перш ніж скопіювати в пункт призначення, щоб пропустити рядок заголовків.
Якщо у файлах CSV не всі однакові стовпці, то вам потрібно визначити, в якому сенсі ви їх "зливаєте" (як SQL JOIN? Або "горизонтально", якщо всі вони мають однакову кількість рядків? Тощо, тощо) ) - нам важко здогадатися, що ви маєте на увазі в такому випадку.
Невелика зміна наведеного вище коду, оскільки він насправді працює некоректно.
Це повинно бути наступним чином ...
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)
Якщо об'єднаний CSV буде використовуватися в Python, просто використовуйте, glob
щоб отримати список файлів, до яких потрібно передати за fileinput.input()
допомогою files
аргументу, а потім використовуйте csv
модуль, щоб прочитати все за один раз.
Досить просто об'єднати всі файли в каталог і об'єднати їх
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)
АБО, ви могли б просто зробити
cat sh*.csv > merged.csv
Ви можете імпортувати CSV, після чого прокрутити всі файли CSV, читаючи їх до списку. Потім запишіть список назад на диск.
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))
Вищезазначене не надто надійне, оскільки воно не обробляє помилок і не закриває будь-які відкриті файли. Це має спрацювати незалежно від того, чи мають окремі файли один або кілька рядків даних CSV. Також я не запускав цей код, але він повинен дати вам уявлення про те, що робити.
Над рішенням, яке зробило @Adders, а пізніше вдосконалило @varun, я реалізував невелике вдосконалення, залишивши весь об'єднаний CSV лише з головним заголовком:
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()
З найкращими побажаннями!!!
Ви можете просто використовувати вбудовану csv
бібліотеку. Це рішення буде працювати, навіть якщо деякі з ваших файлів CSV мають дещо інші назви стовпців або заголовки, на відміну від інших найкращих відповідей.
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)
Об’єднаний файл міститиме всі можливі стовпці ( header_keys
), які можна знайти у файлах. Будь-які відсутні стовпці у файлі відображатимуться як порожні / порожні (але з збереженням решти даних файлу).
Примітка:
csv
бібліотекою, але замість використання DictReader
& DictWriter
вам доведеться працювати з базовим reader
& writer
.merged_rows
список).Я змінив те, що @wisty сказав, що працює з python 3.x, для тих з вас, у кого є проблеми з кодуванням, я також використовую модуль os, щоб уникнути жорсткого кодування
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()
Ось сценарій:
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())
Оновлення відповіді Вісті для 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()
Скажімо, у вас є 2 csv
таких файли:
csv1.csv:
id,name
1,Armin
2,Sven
csv2.csv:
id,place,year
1,Reykjavik,2017
2,Amsterdam,2018
3,Berlin,2019
і ви хочете, щоб результат був таким: csv3.csv:
id,name,place,year
1,Armin,Reykjavik,2017
2,Sven,Amsterdam,2018
3,,Berlin,2019
Тоді ви можете використовувати такий фрагмент для цього:
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)
За допомогою циклу ви можете досягти того самого результату для кількох файлів, що і у вашому випадку (200 файлів CSV).
Якщо файли не пронумеровані в порядку, скористайтеся безпроблемним підходом нижче: Python 3.6 на машині 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)
Проста у використанні функція:
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()