2

[Python3 を使用] 読み取りたい csv ファイルがあり、重複の「特別な」ケースを削除します。スクリプトは、ヘッダーを尊重しながら、重複除去された csv を csv に出力する必要があります。

例を挙げて説明するのが最善です。csv ファイルは次のようになります。

ID  Name    HeaderX HeaderY HeaderZ ...
1   A       string  float   string  ...
1   A       string  float   string  ...
1   A       string  float   string  ...
2   A       string  float   string  ...
2   B       string  float   string  ...
3   A       string  float   string  ...
4   B       string  float   string  ...
5   C       string  float   string  ...
6   D       string  float   string  ...
... ...     ...     ...     ...     ...

ここでは、ID=1 と ID=2 の重複行がありますが、名前が同じ重複行をすべて保持したいと考えています。したがって、この例では、ID=1 のすべてのインスタンスを保持したいのですが、ID=2 のすべてのインスタンスを削除します。つまり、Name に 1 つ以上のバリエーションがある重複するすべての行を削除します。(それは理にかなっていますか?!)

現在、このスレッドに基づいて、次のコード (以下) があります。ただし、2 つの列に基づいて重複を削除し、ID=2 のすべてのインスタンスを残し、ID=1 の行を削除するという、まったく逆のことを行います。

また、理想的には、削除された重複の数をスクリプトに出力させたいと思います。

import csv

filename = 'testing.csv'
outfile = 'outfile.csv'

with open(outfile, 'w') as fout:
    writer = None
    entries = set()
    with open(filename, 'r') as fin:
        reader = csv.DictReader(fin)

        if not writer:
            writer = csv.DictWriter(fout, lineterminator='\n', fieldnames=reader.fieldnames)
            writer.writeheader()

        for row in reader:
            key = (row['ID'], row['Name'])

            if key not in entries:
                writer.writerow(row)
                entries.add(key)
4

1 に答える 1

2

行が ID で並べ替えられている場合は、次のコードを使用できます。

import csv
import itertools
import operator

filename = 'testing.csv'
outfile = 'outfile.csv'
ndups = 0

with open(filename, 'r') as fin, open(outfile, 'w') as fout:
    reader = csv.DictReader(fin)
    writer = csv.DictWriter(fout, lineterminator='\n', fieldnames=reader.fieldnames)
    for id_, grp in itertools.groupby(reader, key=operator.itemgetter('ID')):
        rows = list(grp)
        if len({row['Name'] for row in rows}) > 1:
            ndups += len(rows)
            continue
        writer.writerows(rows)

print('{} duplicates.'.format(ndups))
于 2013-06-21T11:19:56.350 に答える