【问题标题】:Appending rows to CSV in Python with column-specific duplicate filter使用特定于列的重复过滤器在 Python 中将行附加到 CSV
【发布时间】:2013-11-12 01:28:05
【问题描述】:

所以我希望 Python 使用 csv 读取器/写入器获取目录中的所有 CSV 并将它们组合起来,同时过滤掉第二列中包含与任何其他行的值重复的任何行。

这是我无法运行的脚本:

import csv
import glob

with open('merged.csv','a') as out:
    seen = set()
    output = []
    out_writer = csv.writer(out)
    csv_files = [f for f in glob.glob('*.csv') if 'merged' not in f]
#csv_files = glob.glob('*.csv') 
     # I'd like to use all files including the output so that I don't
     # have to rename it when reusing the script - it should dupe-filter itself!
for filename in csv_files:
    with open(filename, 'rb') as ifile:
        read = csv.reader(ifile, delimiter=',')
        for row in read:
            if row[1] not in seen:
                seen.add(row[1])
                if row: #was getting extra rows
                    output.append(row)
out_writer.writerows(output)

我觉得我一定错过了一些简单的东西。我的文件每个大小约为 100MB,我最终希望自动执行此操作,以便不同的计算机可以共享一个合并文件以进行重复检查。

为了获得额外的积分,我将如何更改它以检查同时具有 row[1]row[2] 的行? (当然,一旦欺骗过滤器和自我包含起作用......)

【问题讨论】:

    标签: python list csv append


    【解决方案1】:

    我建议使用 pandas 而不是 csv 编写器。我会把你的代码改写成这样:

    import pandas as pd
    import glob
    
    data = pd.concat([pd.DataFrame.from_csv(file) for
                      file in glob.glob("*.csv")]).drop_duplicates(cols=COLNAME_LIST)
    data.to_csv('merged.csv')
    

    我没有测试过这段代码,因为我没有大量的 csv 文件,但我之前成功地写过类似的东西

    【讨论】:

    • 哎呀,如果你觉得万圣节的各种疯狂,你甚至可以把它做成一个单行字pd.concat([pd.DataFrame.from_csv(file) for file in glob.glob("*.csv")]).drop_duplicates(cols=COLNAME_LIST).to_csv('merged.csv')
    • 太棒了 - 我一直在考虑与 pandas 合作,因为我实际上有很多这类东西可以使用。现在进入比等到有必要并且必须翻译所有内容更有意义。这将仅根据第 2 列检查重复项,还是会删除任何列条目上的重复项?我真的需要查一下 pandas 的基础知识。
    • 您可以向它传递您想要检查重复项的列列表(请参阅上面的 COLNAME_LIST)。在列上添加标签会有所帮助(只需将文件中的第一行作为标题名称即可),但如果不这样做,它们将只有数字标题。您应该注意的另一件事是索引,因为它们会自动创建为每行中的第一个值。我不确定您的 csv 文件的结构,但希望这对您来说不是问题。无论哪种方式都没什么大不了的
    • 我收到AttributeError: 'module' object has no attribute 'concat'
    • 你用的是什么版本的熊猫?我在 0.12
    【解决方案2】:

    这不仅仅是 pandas 可能需要的少量行,因为它是 Python 标准,但另一方面它相对简单,可以过滤多个列值,并处理重新读取以前的结果。它使用fileinputmodule 允许将其多个输入文件视为单个连续的数据行流。

    import csv
    import fileinput
    import glob
    import os
    
    merged_csv = 'merged.csv'
    columns = (1, 2)  # columns used for filtering
    pathname = '*.csv'
    tmpext = os.extsep + "tmp"
    csv_files = glob.glob(pathname)
    
    if merged_csv not in csv_files:
        prev_merged = None
    else:
        prev_merged = merged_csv + tmpext
        os.rename(merged_csv, prev_merged)
        csv_files[csv_files.index(merged_csv)] = prev_merged
    
    with open(merged_csv, 'wb') as ofile:
        csv_writer = csv.writer(ofile)
        written = set()  # unique combinations of column values written
        csv_stream = fileinput.input(csv_files, mode='rb')
        for row in csv.reader(csv_stream, delimiter=','):
            combination = tuple(row[col] for col in columns)
            if combination not in written:
                csv_writer.writerow(row)
                written.add(combination)
    
    if prev_merged:
        os.unlink(prev_merged)  # clean up
    
    print '{!r} file {}written'.format(merged_csv, 're' if prev_merged else '')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-15
      • 2014-04-19
      • 2020-10-01
      • 2019-10-24
      • 2020-11-07
      相关资源
      最近更新 更多