как объединить 200 файлов csv в Python

83

Ребята, у меня есть 200 отдельных файлов csv с именами от SH (1) до SH (200). Я хочу объединить их в один файл csv. Как мне это сделать?

Чак
источник
3
Как бы вы их слили? (Объединить строки, ...)
Tur1ng
6
Как вы хотите, чтобы они были объединены? Каждая строка в CSV-файле - это строка. Итак, один простой вариант - просто объединить все файлы вместе.
Джон-Эрик
Каждый файл состоит из двух столбцов. Я хочу объединить их в один файл с двумя столбцами последовательно.
Чак
1
@Chuck: Как насчет того, чтобы взять все ответы в ваших комментариях (на вопрос и ответы) и обновить свой вопрос?
tumultous_rooster
2
Этот вопрос следует называть "Как объединить ..." вместо "как объединить ..."
colidyre

Ответы:

95

Как сказал 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()
туманный
источник
11
вы можете использовать f.__next__()вместо этого, если f.next()в python3.x.
tsveti_iko
5
Просто примечание: можно использовать with openсинтаксис и не .close()загружать файлы вручную .
FatihAkici 08
2
какая разница между f.next()и f.__next__()? когда я использую первое, я получил'_io.TextIOWrapper' object has no attribute 'next'
Джейсон Гол
прежде, чем fout.write(line)я бы сделал:if line[-1] != '\n': line += '\n'
shisui
65

Почему ты просто не можешь sed 1d sh*.csv > merged.csv?

Иногда вам даже не нужно использовать питон!

блинзай
источник
21
В windows C: \> copy * .csv merged.csv
авиаудар
6
Скопируйте информацию заголовка из одного файла: sed -n 1p some_file.csv> merged_file.csv Скопируйте все, кроме последней строки из всех других файлов: sed 1d * .csv >> merged_file.csv
ведет себя
3
@blinsay Он также добавляет заголовок в каждый файл CSV к объединенному файлу.
Мина
5
Как использовать эту команду, не копируя информацию заголовка для каждого последующего файла после первого? Кажется, я постоянно получаю информацию о заголовке.
Джо
2
Это здорово, если вам не нужно удалять заголовок!
Blairg23
51

Используйте принятый ответ 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 )
Скоттлиттл
источник
@ wisty, @ Andy, предположим, что все файлы имеют заголовки для каждой строки - некоторые строки с разными заголовками. Нет заголовков для 2 столбцов в каждом файле. Как можно слить, чтобы для каждого файла добавлялся только столбец.
Gathide
Куда экспортируется файл?
@ dirtyysocks45, я изменил ответ, чтобы было понятнее.
scottlittle
добавить сортировать: combined_csv = pd.concat ([pd.read_csv (F) для F в именах файлов], вроде = False)
sailfish009
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()
призрачная собака74
источник
13

Я просто просмотрю еще один пример кода в корзине

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)
Норфельдт
источник
2
@Andy Я не вижу разницы между stackoverflow, напоминающим мне проголосовать за ответ, и тем, что я напоминаю людям, чтобы они выразили свою признательность (проголосовав за), если они сочли мой ответ полезным. Я знаю, что это не Facebook, и я не охотник за
лайками
1
Это обсуждалось ранее и каждый раз признавалось неприемлемым.
Энди
10

Это зависит от того, что вы подразумеваете под «слиянием» - у них одинаковые столбцы? У них есть заголовки? Например, если все они имеют одинаковые столбцы и не имеют заголовков, достаточно простой конкатенации (откройте целевой файл для записи, переберите источники, открывающие каждый для чтения, используйте shutil.copyfileobj из открытого для чтения источника в открытое для записи место назначения, закройте источник, продолжайте цикл - используйте withоператор для закрытия от вашего имени). Если у них одинаковые столбцы, но также и заголовки, вам понадобится по одному readlineв каждом исходном файле, кроме первого, после того, как вы откроете его для чтения, прежде чем копировать его в место назначения, чтобы пропустить строку заголовков.

Если в файлах CSV не все одинаковые столбцы, вам нужно определить, в каком смысле вы их «объединяете» (например, SQL JOIN? Или «по горизонтали», если все они имеют одинаковое количество строк? И т. Д. ) - нам сложно догадаться, что вы имеете в виду в этом случае.

Алекс Мартелли
источник
В каждом файле есть два столбца с заголовками. Я хочу объединить их в один файл с двумя столбцами последовательно.
Чак
4

Небольшое изменение в приведенном выше коде, поскольку на самом деле он не работает правильно.

Должно быть так ...

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)
Сумматоры
источник
3

Если объединенный CSV будет использоваться в Python, просто используйте его, globчтобы получить список файлов, которые нужно передать fileinput.input()через filesаргумент, а затем используйте csvмодуль, чтобы прочитать все это за один раз.

Игнасио Васкес-Абрамс
источник
3

Довольно просто объединить все файлы в каталоге и объединить их

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)
Варун
источник
3

Если вы работаете с linux / mac, вы можете это сделать.

from subprocess import call
script="cat *.csv>merge.csv"
call(script,shell=True)
Солнечный
источник
2

ИЛИ, вы могли бы просто сделать

cat sh*.csv > merged.csv
Нанаши Но Гомбе
источник
1

Вы можете импортировать 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. Также я не запускал этот код, но он должен дать вам представление о том, что делать.

cnobile
источник
1

В решении, которое сделало @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()

С уважением!!!

Фабиан Миранда Муньос
источник
1

Вы можете просто использовать встроенную 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-файлы не имеют заголовков. В этом случае вы все равно можете использовать csvбиблиотеку, но вместо использования DictReader& DictWriterвам придется работать с базовым reader& writer.
  • Это может вызвать проблемы, когда вы имеете дело с большими данными, так как весь контент хранится в памяти ( merged_rowsсписок).
shad0w_wa1k3r
источник
0

Я изменил то, что @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()
Марьям Пашми
источник
0

Вот сценарий:

  • Конкатенация файлов CSV с именем 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())
x0s
источник
0

Обновление ответа wisty для 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()
ishandutta2007
источник
0

Допустим, у вас есть 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).

tsveti_iko
источник
0

Если файлы пронумерованы не по порядку, воспользуйтесь беспроблемным подходом, описанным ниже: 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)
Азаде Фейзпур
источник
0

Простая в использовании функция:

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)
Кен Шибата
источник
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()
Сунит Деогам
источник