簡體   English   中英

合並多個CSV文件而不重復標題(使用Python)

[英]Merging multiple CSV files without headers being repeated (using Python)

我是Python的初學者。 我有多個CSV文件(超過10個),並且它們都具有相同數量的列。 我想將它們合並到一個CSV文件中,我不會重復標題。

所以基本上我需要只有第一行包含所有標題,然后我需要合並所有CSV文件中的所有行。 我該怎么做呢?

這是我到目前為止所嘗試的內容。

import glob
import csv



with open('output.csv','wb') as fout:
    wout = csv.writer(fout,delimiter=',') 
    interesting_files = glob.glob("*.csv") 
    for filename in interesting_files: 
        print 'Processing',filename 
    # Open and process file
        h = True
        with open(filename,'rb') as fin:
                fin.next()#skip header
        for line in csv.reader(fin,delimiter=','):
                wout.writerow(line)

如果您使用的是Linux系統:

head -1 director/one_file.csv > output csv   ## writing the header to the final file
tail -n +2  director/*.csv >> output.csv  ## writing the content of all csv starting with second line into final file

雖然我認為最好的答案是來自@valentin的答案,但您可以在不使用csv模塊的情況下完成此操作:

import glob

interesting_files = glob.glob("*.csv") 

header_saved = False
with open('output.csv','wb') as fout:
    for filename in interesting_files:
        with open(filename) as fin:
            header = next(fin)
            if not header_saved:
                fout.write(header)
                header_saved = True
            for line in fin:
                fout.write(line)

如果您不介意開銷,可以使用隨附常見python發行版的pandas。 如果您計划使用speadsheet表做更多,我建議使用pandas而不是嘗試編寫自己的庫。

import pandas as pd
import glob
interesting_files = glob.glob("*.csv")
df_list = []
for filename in sorted(interesting_files):
    df_list.append(pd.read_csv(filename))
full_df = pd.concat(df_list)

full_df.to_csv('output.csv')

關於熊貓的更多信息。 因為它是為了處理像數據這樣的電子表格,所以它知道第一行是標題。 在讀取CSV時,它將數據表與標題分開,標題保存為數據dataframedataframe ,即pandas中的標准數據類型。 如果你連接其中幾個dataframes它只會連接dataframes ,如果它們的標題是相同的。 如果標題不相同則失敗並給出錯誤。 如果您的目錄被來自其他來源的CSV文件污染,可能是件好事。

另一件事:我剛剛在interesting_files周圍添加了sorted() 我假設您的文件按順序命名,並且應該保留此順序。 我不確定glob,但os函數不一定返回按名稱排序的文件。

你的縮進是錯誤的,你需要將循環放在with塊中。 您還可以將文件對象傳遞給writer.writerows。

import csv
with open('output.csv','wb') as fout:
    wout = csv.writer(fout)
    interesting_files = glob.glob("*.csv")
    for filename in interesting_files:
        print 'Processing',filename
        with open(filename,'rb') as fin:
                next(fin) # skip header
                wout.writerows(fin)

您的嘗試幾乎正常,但問題是:

  • 你打開文件進行閱讀,但在寫行之前將其關閉。
  • 你永遠不會寫標題。 你必須寫一次
  • 你還必須從“glob”中排除 output.csv,否則輸出也在輸入中!

這是更正后的代碼,將csv對象直接傳遞給csv.writerows方法,以獲得更短更快的代碼。 還將標題從第一個文件寫入輸出文件。

import glob
import csv

output_file = 'output.csv'
header_written = False

with open(output_file,'w',newline="") as fout:  # just "wb" in python 2
    wout = csv.writer(fout,delimiter=',')
    # filter out output
    interesting_files = [x for x in glob.glob("*.csv") if x != output_file]
    for filename in interesting_files:
        print('Processing {}'.format(filename))
        with open(filename) as fin:
            cr = csv.reader(fin,delmiter=",")
            header = cr.next() #skip header
            if not header_written:
                wout.writerow(header)
                header_written = True
            wout.writerows(cr)

請注意,使用原始逐行處理的解決方案錯過了重要的一點:如果標題是多行的,則它們會失敗,使標題行/重復部分多次失敗,從而有效地破壞文件。

csv模塊(或者pandas)也可以優雅地處理這些情況。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM