Các bạn ơi, mình ở đây có 200 tệp csv riêng biệt có tên từ SH (1) đến SH (200). Tôi muốn hợp nhất chúng thành một tệp csv duy nhất. Tôi làm nó như thế nào?
Các bạn ơi, mình ở đây có 200 tệp csv riêng biệt có tên từ SH (1) đến SH (200). Tôi muốn hợp nhất chúng thành một tệp csv duy nhất. Tôi làm nó như thế nào?
Câu trả lời:
Như ghostdog74 đã nói, nhưng lần này với tiêu đề:
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__()
thay thế nếu f.next()
trong python3.x.
with open
cú pháp và tránh nhập .close()
các tệp theo cách thủ công .
f.next()
và là f.__next__()
gì? khi tôi sử dụng cái cũ, tôi nhận được'_io.TextIOWrapper' object has no attribute 'next'
fout.write(line)
tôi làm:if line[-1] != '\n': line += '\n'
Tại sao bạn không thể chỉ sed 1d sh*.csv > merged.csv
?
Đôi khi bạn thậm chí không cần phải sử dụng python!
Sử dụng câu trả lời StackOverflow được chấp nhận để tạo danh sách các tệp csv mà bạn muốn nối thêm và sau đó chạy mã này:
import pandas as pd
combined_csv = pd.concat( [ pd.read_csv(f) for f in filenames ] )
Và nếu bạn muốn xuất nó thành một tệp csv, hãy sử dụng cái này:
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()
Tôi chỉ sẽ xem qua một ví dụ mã khác trong giỏ
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)
Nó phụ thuộc vào ý bạn khi "hợp nhất" - chúng có các cột giống nhau không? Chúng có tiêu đề không? Ví dụ: nếu tất cả chúng đều có cùng cột và không có tiêu đề, thì nối đơn giản là đủ (mở tệp đích để ghi, lặp qua các nguồn đang mở để đọc, sử dụng shutil.copyfileobj từ nguồn mở để đọc vào đích mở để viết, đóng nguồn, tiếp tục lặp - sử dụng with
câu lệnh để thực hiện việc đóng thay mặt bạn). Nếu chúng có các cột giống nhau, nhưng cũng có tiêu đề, bạn sẽ cần một readline
tệp trên mỗi tệp nguồn ngoại trừ tệp đầu tiên, sau khi bạn mở nó để đọc trước khi bạn sao chép nó vào đích, để bỏ qua dòng tiêu đề.
Nếu tất cả các tệp CSV không có cùng các cột thì bạn cần phải xác định xem bạn đang "hợp nhất" chúng theo nghĩa nào (như SQL JOIN? Hoặc "theo chiều ngang" nếu tất cả chúng có cùng số dòng? V.v., v.v. ) - thật khó để chúng tôi đoán ý bạn trong trường hợp đó.
Nếu CSV đã hợp nhất sẽ được sử dụng trong Python thì chỉ cần sử dụng glob
để lấy danh sách các tệp cần chuyển đến fileinput.input()
thông qua files
đối số, sau đó sử dụng csv
mô-đun để đọc tất cả trong một lần.
Một thay đổi nhỏ đối với mã trên vì nó thực sự không hoạt động chính xác.
Nó sẽ như sau ...
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)
Khá dễ dàng để kết hợp tất cả các tệp trong một thư mục và hợp nhất chúng
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)
HOẶC, bạn chỉ có thể làm
cat sh*.csv > merged.csv
Bạn có thể nhập csv sau đó lặp qua tất cả các tệp CSV đang đọc chúng thành một danh sách. Sau đó, ghi lại danh sách ra đĩa.
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))
Phần trên không mạnh mẽ lắm vì nó không có xử lý lỗi cũng như không đóng bất kỳ tệp nào đang mở. Điều này sẽ hoạt động cho dù các tệp riêng lẻ có một hoặc nhiều hàng dữ liệu CSV trong đó hay không. Ngoài ra, tôi đã không chạy mã này, nhưng nó sẽ cung cấp cho bạn ý tưởng về những gì cần làm.
Thông qua giải pháp tạo ra @Adders và sau đó được cải tiến bởi @varun, tôi cũng đã thực hiện một số cải tiến nhỏ để lại toàn bộ CSV đã hợp nhất chỉ với tiêu đề chính:
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()
Trân trọng!!!
Bạn chỉ cần sử dụng csv
thư viện tích hợp sẵn . Giải pháp này sẽ hoạt động ngay cả khi một số tệp CSV của bạn có tên cột hoặc tiêu đề hơi khác nhau, không giống như các câu trả lời được bình chọn nhiều nhất khác.
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)
Tệp hợp nhất sẽ chứa tất cả các cột có thể có ( header_keys
) có thể được tìm thấy trong tệp. Bất kỳ cột nào vắng mặt trong tệp sẽ được hiển thị dưới dạng trống / trống (nhưng giữ nguyên phần dữ liệu còn lại của tệp).
Ghi chú:
csv
thư viện, nhưng thay vì sử dụng DictReader
& DictWriter
, bạn sẽ phải làm việc với reader
& writer
.merged_rows
danh sách).Tôi đã sửa đổi những gì @wisty nói là hoạt động với python 3.x, đối với những người bạn gặp vấn đề về mã hóa, tôi cũng sử dụng mô-đun os để tránh mã hóa khó
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()
Đây là một kịch bản:
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())
Đang cập nhật câu trả lời của wisty cho 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()
Giả sử bạn có 2 csv
tệp như sau:
csv1.csv:
id,name
1,Armin
2,Sven
csv2.csv:
id,place,year
1,Reykjavik,2017
2,Amsterdam,2018
3,Berlin,2019
và bạn muốn kết quả như thế này csv3.csv:
id,name,place,year
1,Armin,Reykjavik,2017
2,Sven,Amsterdam,2018
3,,Berlin,2019
Sau đó, bạn có thể sử dụng đoạn mã sau để làm điều đó:
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)
Với sự trợ giúp của vòng lặp, bạn có thể đạt được cùng một kết quả cho nhiều tệp như trong trường hợp của bạn (200 tệp csv).
Nếu các tệp không được đánh số theo thứ tự, hãy thực hiện cách tiếp cận đơn giản dưới đây: Python 3.6 trên máy 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)
Một chức năng dễ sử dụng:
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()