【问题标题】:Remove duplicates in a csv file based on two columns?基于两列删除csv文件中的重复项?
【发布时间】:2015-12-28 13:12:24
【问题描述】:

我有一个必须读取的 CSV,并在写入之前删除了重复值。

重复值将基于两列(日期、价格)(AND 条件语句)。因此,在下面的示例中,第 1 行、第 2 行和第 4 行将被写入 CSV。第 3 行将被视为重复(因为相同的日期和价格与第 1 行匹配)并将被排除(未写入 CSV)。

address      floor       date         price
40 B STREET    18        3/29/2015    2200000
40 B STREET    23        1/7/2015     999000
40 B STREET    18        3/29/2015    2200000
40 B STREET    18        4/29/2015    2200000

【问题讨论】:

    标签: csv python-3.x conditional duplicate-removal


    【解决方案1】:

    您可以使用DictReaderDictWriter 来完成您的任务。

    import csv
    
    def main():
    """Read csv file, delete duplicates and write it."""
        with open('test.csv', 'r',newline='') as inputfile:
            with open('testout.csv', 'w', newline='') as outputfile:
                duplicatereader = csv.DictReader(inputfile, delimiter=',')
                uniquewrite = csv.DictWriter(outputfile, fieldnames=['address', 'floor', 'date', 'price'], delimiter=',')
                uniquewrite.writeheader()
                keysread = []
                for row in duplicatereader:
                   key = (row['date'], row['price'])
                   if key not in keysread:
                       print(row)
                       keysread.append(key)
                       uniquewrite.writerow(row)
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

      【解决方案2】:

      虽然不在标准库中,但pandas 非常适合这类事情:

      import pandas as pd
      records = pd.read_csv('test.csv')
      deduped = records.drop_duplicates(['date', 'price'])
      deduped.to_csv('deduped.csv', index=False)
      

      这种方法的缺点是一次性将所有数据读入内存。但是,如果您的数据集在内存中非常合适,那么增加清晰度和表现力可能是值得的——特别是如果您要对这样的表格数据进行额外的操作。

      【讨论】:

        【解决方案3】:

        您可以使用set 保留写入的行,并在每次迭代检查中,如果该行已被写入,请不要写入它,并使用tempfile.NamedTemporaryFile 重写您的文件:

        import csv
        from tempfile import NamedTemporaryFile
        import shutil
        
        seen=set()
        tempfile = NamedTemporaryFile(delete=False)
        
        with open('file_name.csv', newline='') as csvfile:
             spamreader = csv.reader(csvfile, delimiter='\t')
             spamwriter = csv.writer(csvfile, delimiter='\t')
             for row in spamreader:
                 date=row[2]
                 if date not in seen:
                    spamwriter.writerow(row)
                 seen.add(date)
        shutil.move(tempfile.name, file_name)
        

        【讨论】:

        • 价格呢?我只想排除“日期”和“价格”值是否都在以前的记录中。如果它只是以前记录中的日期值或价格值,则包括它。因此,它必须是一个条件语句。
        • @user3062459 所以只需将tuple(row[2:]) 放在seen 上并检查一下。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-03
        相关资源
        最近更新 更多