web-dev-qa-db-ja.com

pythonで行CSVを削除する方法

2つのcsvファイル(fileAとfileB)を比較し、fileBに見つからない行をfileAから削除しようとしています。 3番目のファイルを作成せずにこれを実行できるようにしたい。 csvライターモジュールを使用してこれを実行できると思いましたが、今は自分自身を推測しています。

現在、次のコードを使用して、ファイルBから比較データを記録しています。

removal_list = set()
with open('fileB', 'rb') as file_b:
    reader1 = csv.reader(file_b)
    next(reader1)
    for row in reader1:
        removal_list.add((row[0], row[2]))

これは私が立ち往生していて、行を削除する方法がわからないところです:

with open('fileA', 'ab') as file_a:
    with open('fileB', 'rb') as file_b:
        writer = csv.writer(file_a)
            reader2 = csv.reader(file_b)
            next(reader2)
            for row in reader2:
                if (row[0], row[2]) not in removal_list:
                # If row was not present in file B, Delete it from file A.
                #stuck here:  writer.<HowDoIRemoveRow>(row)
10
justin

このソリューションでは、 fileinput with _inplace=True_を使用します。これにより、一時ファイルに書き込みが行われ、最後にファイル名が自動的に変更されます。ファイルから行を削除することはできませんが、必要な行だけで書き換えることはできます。

キーワード引数_inplace=1_がfileinput.input()またはFileInputコンストラクターに渡されると、ファイルはバックアップファイルに移動され、標準出力は入力ファイルに送られます(バックアップファイルと同じ名前のファイルがすでに存在する場合は、サイレントに置き換えられます)。これにより、入力ファイルを所定の場所に書き換えるフィルターを作成できます。

fileA

_h1,h2,h3
a,b,c
d,e,f
g,h,i
j,k,l
_

fileB

_h1,h2,h3
a,b,c
1,2,3
g,h,i
4,5,6
_

_import fileinput, sys, csv

with open('fileB', 'rb') as file_b:
    r = csv.reader(file_b)
    next(r) #skip header
    seen = {(row[0], row[2]) for row in r}

f = fileinput.input('fileA', inplace=True) # sys.stdout is redirected to the file
print next(f), # write header as first line

w = csv.writer(sys.stdout) 
for row in csv.reader(f):
   if (row[0], row[2]) in seen: # write it if it's in B
       w.writerow(row)
_

fileA

_h1,h2,h3
a,b,c    
g,h,i
_
8
jamylak

CSVはデータベース形式ではありません。全体として読み書きされます。途中の行を削除することはできません。したがって、3番目のファイルを作成せずにこれを行う唯一の方法は、ファイルを完全にメモリに読み込み、問題のある行なしで書き出すことです。

ただし、一般的には3番目のファイルを使用することをお勧めします。

3
Lennart Regebro

Lennartが説明したように、CSVファイルを繰り返し処理するときにその場でCSVファイルを変更することはできません。

3番目のファイルを作成することに本当に反対している場合は、 StringIO で文字列バッファを使用することを検討することをお勧めします。これは、ファイルAの新しい目的のコンテンツをメモリに構築することです。スクリプトの最後で、バッファの内容をファイルAに書き込むことができます。

from cStringIO import StringIO


with open('fileB', 'rb') as file_b:
    new_a_buf = StringIO()
    writer = csv.writer(new_a_buf)
    reader2 = csv.reader(file_b)
    next(reader2)
    for row in reader2:
        if (row[0], row[2]) not in removal_list:
            writer.writerow(row)

# At this point, the contents (new_a_buf) exist in memory
with open('fileA', 'wb') as file_a:
    file_a.write(new_a_buf.getvalue())
3
David Cain