Pythonで200のcsvファイルをマージする方法


83

みんな、私はここにSH(1)からSH(200)までの名前の200の別々のcsvファイルを持っています。それらを1つのcsvファイルにマージしたいと思います。どうすればいいですか?


3
どのようにそれらをマージしますか?(行を連結、...)
tur1ng 2010年

6
それらをどのようにマージしますか?CSVファイルの各行は1行です。したがって、1つの簡単なオプションは、すべてのファイルを連結することです。
Jon-Eric

各ファイルには2つの列があります。それらを2列連続で1つのファイルにマージしたいと思います。
チャック

1
@Chuck:コメント(質問と回答)のすべての回答を受け取り、質問を更新するのはどうですか?
tumultous_rooster 2015

2
この質問には、「マージする方法...」ではなく「連結する方法...」という名前を付ける必要があります
colidyre 2018

回答:


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
python3.xのf.__next__()場合f.next()は、代わりに使用できます。
tsveti_iko

5
注:with open構文を使用して.close()、ファイルを手動で作成する必要はありません。
FatihAkici

2
違いは何だf.next()とはf.__next__()?前者を使用すると、次のようになりました'_io.TextIOWrapper' object has no attribute 'next'
Jason Goal

fout.write(line)私がする前に:if line[-1] != '\n': line += '\n'
shisui 2018年

65

なぜあなたはただできないのですsed 1d sh*.csv > merged.csvか?

Pythonを使用する必要がない場合もあります。


21
Windowsでは、C:\>コピー* .csv merged.csv
空爆

6
1つのファイルからヘッダー情報をコピーします。sed-n1psome_file.csv> merged_file.csv他のすべてのファイルから最後の行を除くすべてをコピーします:sed 1d * .csv >> merged_file.csv
2011年

3
@blinsayただし、各CSVファイルのヘッダーをマージされたファイルにも追加します。
ミナ2014年

5
最初のファイルの後に後続の各ファイルのヘッダー情報をコピーせずに、このコマンドをどのように使用しますか?ヘッダー情報が繰り返しポップアップするようです。
ジョー

2
これは、ヘッダーを削除する必要がない場合に最適です。
Blairg23 2016年

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 2017年

ファイルはどこにエクスポートされますか?

@ dirtysocks45、私はこれをより明確にするために答えを変更しました。
scottlittle 2017

並べ替えを追加:combined_csv = pd.concat([pd.read_csv(f)for f in filenames]、sort = False)
sailfish0

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()

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回答に投票するように通知するスタックオーバーフローと、回答が役に立った場合は(投票することで)感謝の気持ちを共有するように通知するスタックオーバーフローの違いがわかりません。..私は、これはFacebookのではないことを知っていると私は次のように、ハンターはないよ
Norfeldt

1
それはされてきた議論 以前に、それがされている各時間があるとみなさ容認できません。
アンディ

10

「マージ」の意味によって異なりますが、同じ列がありますか?ヘッダーはありますか?たとえば、すべてに同じ列があり、ヘッダーがない場合は、単純な連結で十分です(書き込み用に宛先ファイルを開き、読み取り用にそれぞれを開いているソースをループし、読み取り用に開いているソースからshutil.copyfileobjを使用して書き込み先を開き、ソースを閉じ、ループを続けます-withステートメントを使用して、代わりに閉じます)。同じ列があり、ヘッダーもある場合はreadline、最初のファイルを除く各ソースファイルで、読み取り用に開いた後、コピー先にコピーする前に、ヘッダー行をスキップする必要があります。

CSVファイルの列がすべて同じでない場合は、それらを「マージ」する意味を定義する必要があります(SQL JOINのように、またはすべて同じ行数の場合は「水平方向に」など)。 )-その場合、あなたが何を意味するのかを推測するのは難しいです。


各ファイルには、ヘッダー付きの2つの列があります。それらを2列連続で1つのファイルにマージしたいと思います。
チャック

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

ディレクトリ内のすべてのファイルを結合してマージするのは非常に簡単です

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)


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))

上記はエラー処理がなく、開いているファイルを閉じないため、それほど堅牢ではありません。これは、個々のファイルに1行以上のCSVデータが含まれているかどうかに関係なく機能するはずです。また、私はこのコードを実行しませんでしたが、それはあなたに何をすべきかについての考えを与えるはずです。


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リスト)に保存されているため、大量のデータを処理しているときに問題が発生する可能性があります。

0

@wistyがpython3.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

スクリプトは次のとおりです。

  • に名前が付けられSH1.csvた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())

0

Python3のwistyの答えを更新する

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()

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ファイル)で同じ結果を得ることができます。


0

ファイルに順番に番号が付けられていない場合は、以下の手間のかからないアプローチを採用してください。Windowsマシン上のPython 3.6:

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()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.