Python 在csv文件中标记重复项

Python 在csv文件中标记重复项,python,csv,duplicates,Python,Csv,Duplicates,下面的示例说明了我遇到的一个问题: "ID","NAME","PHONE","REF","DISCARD" 1,"JOHN",12345,, 2,"PETER",6232,, 3,"JON",12345,, 4,"PETERSON",6232,, 5,"ALEX",7854,, 6,"JON",12345,, 我想检测列“PHONE”中的重复项,并使用列“REF”标记后续重复项,值指向第一项的“ID”,值“DISCARD”列为“Yes” 那么,我该怎么做呢? 我试过这个代码,但我的逻辑当然不正

下面的示例说明了我遇到的一个问题:

"ID","NAME","PHONE","REF","DISCARD"
1,"JOHN",12345,,
2,"PETER",6232,,
3,"JON",12345,,
4,"PETERSON",6232,,
5,"ALEX",7854,,
6,"JON",12345,,
我想检测列“PHONE”中的重复项,并使用列“REF”标记后续重复项,值指向第一项的“ID”,值“DISCARD”列为“Yes”

那么,我该怎么做呢? 我试过这个代码,但我的逻辑当然不正确

import csv
myfile = open("C:\Users\Eduardo\Documents\TEST2.csv", "rb")
myfile1 = open("C:\Users\Eduardo\Documents\TEST2.csv", "rb")

dest = csv.writer(open("C:\Users\Eduardo\Documents\TESTFIXED.csv", "wb"), dialect="excel")

reader = csv.reader(myfile)
verum = list(reader)
verum.sort(key=lambda x: x[2])
for i, row in enumerate(verum):
    if row[2] == verum[i][2]:
        verum[i][3] = row[0]

print verum

非常感谢您的指导和帮助。

听起来像是家庭作业。由于这是一个CSV文件(因此更改记录大小几乎是不可能的),因此最好先将整个文件加载到内存中,并在将其写入新文件之前对其进行操作。创建作为文件原始行的字符串列表。然后创建一张地图,在地图中插入电话号码(钥匙)和值(id)。在插入之前,如果号码已经存在,请查找该号码,然后更新包含重复电话号码的线路。如果地图中还没有,请插入(电话,id)对

产出:

['1', 'JOHN', '12345', '1', '']
['2', 'PETER', '6232', '2', '']
['3', 'JON', '12345', '1', 'Yes']
['4', 'PETERSON', '6232', '2', 'Yes']
['5', 'ALEX', '7854', '5', '']
['6', 'JON', '12345', '1', 'Yes']

将数据写回读卡器;-)

我知道一件事。我知道您不必将整个文件读入内存即可完成此操作

import csv
myfile = "C:\Users\Eduardo\Documents\TEST2.csv"

dest = csv.writer(open("C:\Users\Eduardo\Documents\TESTFIXED.csv", "wb"), dialect="excel")

phonedict = {}

for row in cvs.reader(open(myfile, "r")):
    # setdefault sets the value to the second argument if it hasn't been set, and then
    # returns what the value in the dictionary is.
    firstid = phonedict.setdefault(row[2], row[0])
    row[3] = firstid
    if firstid is not row[0]:
       row[4] = "Yes"
    dest.writerow(row)

在运行时,您必须在内存中保存的唯一内容是电话号码到其ID的映射

map = {}
with open(r'c:\temp\input.csv', 'r') as fin:
    reader = csv.reader(fin)
    with open(r'c:\temp\output.csv', 'w') as fout:
        writer = csv.writer(fout)
        # omit this if the file has no header row
        writer.writerow(next(reader))
        for row in reader:
            (id, name, phone, ref, discard) = row
            if map.has_key(phone):
                ref = map[phone]
                discard = "YES"
            else:
                map[phone] = id
            writer.writerow((id, name, phone, ref, discard))

我处理的是40k以上的大型csv文件,这是通过Access消除复制的最简单方法。 1.创建新数据库, 表选项卡获取外部数据 3.保存表格。 4.查询选项卡新建查找重复向导(匹配电话字段、显示所有字段和计数) 5.保存查询(导出有.txt但名称为dupes.txt) 6.将查询结果作为新表导入,不要导入重复计数的字段。。 7.查询查找不匹配(按电话字段匹配,在结果中显示所有字段。保存查询,然后导出为.txt,但名称为unique.txt) 8.将唯一文件导入现有表(重复)
9.您现在可以保存并再次导出到所需的任何类型的文件中,并且不存在任何副本。

+1一个非常明确和实用的解决方案:不使用模糊诡辩(dict.setdefault和itertools.groupby),并使用名称而不是数字作为列。是的,setdefault确实让我的问题变得不那么清楚。我试图尽可能地提高效率,但这在这里可能不是必需的。您的“with”语句可能会导致文件在读卡器或写入器仍连接到它们时关闭。当第二个“with”的范围结束时,fout将关闭。但还是有人可以打电话给writer.writerow()。@omnifarious:你应该保持安静,不要让我再看一遍你的答案:-)你似乎依靠精确匹配来确定两个电话号码是否重复。这只在教室里很常见。在现实世界中,在美国/加拿大/etc电话系统中,相同的电话号码可以写为12345678、1234-5678、1234-5678、(555)1234-5678、+1-555-1234-5678等。。。在其他区域插入前导零,例如+61-412-345-678和(0412)345-678是澳大利亚的同一款移动电话,也称为“手机”。多人也可以共享同一个非移动电话号码;您确定在放弃之前不应该检查名称吗?对于我的需要,这里的示例过于简化。数据经过了一些清理和标准化,所有电话数据都在国内。我将解释真实情况:我在Excel电子表格中有我们客户(公司)的数据库。然后我插入了一大堆来自黄页的条目。在过去,当发现重复项时,我们只是删除了该行。但现在我尝试使用引用和标记“discard”,尤其是处理有点类似的条目。我第一次是手动操作的,它会花费我太长时间来输入大约6000个条目!在首先测试phone并分析结果之后,我打算对address字段使用difflib.SequenceMatcher。它在我的测试用例中运行得很好。-1。。。原因(1)使用dict.setdefault(需要解释)(2)使用下标而不是有意义的列名(3)使用
不是
而不是“!=”(这需要仔细的读者分析代码以确保其正常工作)(4)不在包含反斜杠的文件名的字符串常量上使用
r
前缀(5)无条件地设置行[3],而不是仅当存在重复行时(如OP所指定)。感谢Omnifarious,感谢你第一个回答并给我指出了一个使用字典的解决方案。也感谢你纠正了你第一次试图帮助我的错误。@John Machin,最后一点的操作是错误的。输出清楚地表明id列是无条件设置的。是的,它听起来确实像一个,但不是。在一个非程序员的工作环境中,真正的工作就是真正的工作。我只是简化了代码,把重点放在表达问题的方法上。我很高兴地发现使用dicts是一条可行之路。我确实需要更多地了解itertools.grouby。但我还是不太明白。
import csv
myfile = "C:\Users\Eduardo\Documents\TEST2.csv"

dest = csv.writer(open("C:\Users\Eduardo\Documents\TESTFIXED.csv", "wb"), dialect="excel")

phonedict = {}

for row in cvs.reader(open(myfile, "r")):
    # setdefault sets the value to the second argument if it hasn't been set, and then
    # returns what the value in the dictionary is.
    firstid = phonedict.setdefault(row[2], row[0])
    row[3] = firstid
    if firstid is not row[0]:
       row[4] = "Yes"
    dest.writerow(row)
map = {}
with open(r'c:\temp\input.csv', 'r') as fin:
    reader = csv.reader(fin)
    with open(r'c:\temp\output.csv', 'w') as fout:
        writer = csv.writer(fout)
        # omit this if the file has no header row
        writer.writerow(next(reader))
        for row in reader:
            (id, name, phone, ref, discard) = row
            if map.has_key(phone):
                ref = map[phone]
                discard = "YES"
            else:
                map[phone] = id
            writer.writerow((id, name, phone, ref, discard))