Python - 如何根据单元格从 CSV 中删除重复的单元格/行

Posted

技术标签:

【中文标题】Python - 如何根据单元格从 CSV 中删除重复的单元格/行【英文标题】:Python - How to remove duplicate cells/rows from CSV based on cell 【发布时间】:2014-02-04 03:17:05 【问题描述】:

我有一个逗号分隔的 CSV 文件,其中包含 Cities、States、Zip 和 State Abbreviation。该文件中有重复的引用,带有不同的邮政编码。我的输出只需要列出 1 个城市和一个邮政编码,而不是具有所有不同邮政编码的城市的同名。

这是我在数据中的内容(csv 文件中有 26k 行)

Phoenix, Arizona, 87654, AZ
Phoenix, Arizona, 87655, AZ
Tuscon, Arizona, 98754, AZ
Tuscon, Arizona, 98755, AZ
Tuscon, Arizona, 98756, AZ

我需要的是删除重复的城市行并只保留一个。所以我的输出需要看起来像这样。

Phoenix, Arizona, 87654, AZ
Tuscon, Arizona, 98756, AZ

这是我目前拥有的代码,它不起作用。

import os, sys, csv

f1 = csv.reader(open('originalcities.csv', 'rb'))
writer = csv.writer(open("output_cities.csv", "wb"))
city = set()
for row in f1:
    if row[1] not in city:
        write.writerow(row)
        city.add( row[1] )

我不确定代码是否对我来说是正确的以获得我正在寻找的输出。当我运行这段代码时,我得到了这个错误。

for row in f1:
_csv.Error: iterator should return strings, not bytes (did you open the file in
text mode?)

非常感谢任何帮助。谢谢。

【问题讨论】:

条目按状态排序?如果是这样,您可以将 row[i - 1] 与 row[i] 进行比较并只保留一个。 许多城市有多个邮政编码。您有什么用例可以忽略城市中的大部分邮政编码? 【参考方案1】:

使用row[1] 表示您为每个州保留一个条目。

您应该在 (row[0], row[1]) 上进行测试(城市/州组合,以避免混淆,例如 Richmond TX 和 Richmond VA)。

import csv

IN_FILE  = 'originalcities.csv'
OUT_FILE = 'output_cities.csv'

def main():
    with open(IN_FILE, 'rb') as inf, open(OUT_FILE, 'wb') as outf:
        incsv, outcsv  = csv.reader(inf), csv.writer(outf)

        # read data and de-duplicate by city and state
        citystates = set()
        for row in incsv:
            citystate = tuple(row[0:2])
            if citystate not in citystates:
                outcsv.writeline(row)
                citystates.add(citystate)

if __name__=="__main__":
    main()

** 编辑:**

根据@Fernando 的建议,这是一个不需要集合的版本,它只是比较连续的行(这要求输入数据已经按排序顺序,或者至少每个城市/州组合的所有出现在一起)。

import csv
from itertools import groupby

IN_FILE   = 'originalcities.csv'
OUT_FILE  = 'output_cities.csv'

def main():
    with open(IN_FILE, 'rb') as inf, open(OUT_FILE, 'wb') as outf:
        incsv  = csv.reader(inf)
        outcsv = csv.writer(outf)
        # Read data and de-duplicate by city and state
        # ! assumes data is already in sorted order !
        for citystate,rows in groupby(incsv, key=lambda row: row[0:2]):
            outcsv.writerow(next(rows))

if __name__=="__main__":
    main()

【讨论】:

我一直在运行此代码,但无法使其正常工作。我添加了这一行 incsv, outcsv = csv.reader(codecs.iterdecode(inf, 'utf-8')), csv.writer(outf) 但仍然无法运行。有什么建议么?谢谢。 @user1953451:它对我来说运行良好(Win7x64,Python 2.7.6)。你运行的是哪个版本的 Python? 我使用的是 3.3.2 版本 要让脚本与 Python 3.3 一起工作,您需要将 open(IN_FILE, 'rb') 更改为 open(IN_FILE, mode='r', newline=''),同样,open(OUT_FILE, 'wb') 应更改为 open(OUT_FILE, mode='w', newline='') 太好了,谢谢@superjump 在进行这些更改后,脚本可以完美运行,并在我需要时删除重复项。感谢 Hugh Bothwell 和 Fernando 帮助我找到解决方案。【参考方案2】:

使用set 删除重复项怎么样?

line_sets = []
full_set = []

with open('file.txt') as inp:
    lines = inp.readlines()

    for i in range(0, len(lines)):
        # strip for precaution
        tokens = [w.strip() for w in lines[i].split(',')[0:2]]
        tmp_set = set(tokens)

        if tmp_set not in line_sets:
            full_set.append(lines[i].split(','))
            line_sets.append(tmp_set)

with open('output.txt', 'w') as out:
    for line in full_set:
        out.write(','.join(line))

输出.txt

Phoenix,Arizona,87654,AZ
Tuscon,Arizona,98754,AZ

【讨论】:

以上是关于Python - 如何根据单元格从 CSV 中删除重复的单元格/行的主要内容,如果未能解决你的问题,请参考以下文章

根据 Python HTML 电子邮件中的单元格值将 HTML 表格单元格从“低到高颜色阴影”着色

单元格从覆盖 UIVIew 中获取单独的颜色

将样式单元格从数据库添加到 DataTable

如何让 tableview 单元格从下到上填充? [关闭]

Excel中如何提取某个单元格从第N个字符开始的内容?

如何将表格视图单元格从一个表格视图移动到新的表格视图