【问题标题】:Merge two CSV files Keeping duplicates合并两个 CSV 文件
【发布时间】:2016-09-28 16:00:03
【问题描述】:

我正在尝试合并两个 csv 文件并保留重复记录。每个文件可能有匹配的记录,一个文件可能有重复的记录(相同的学生 ID 不同的考试成绩),一个文件可能在另一个文件中没有匹配的学生记录。下面的代码按预期工作,但是如果存在重复记录,则仅将第二条记录写入合并文件。我查看了许多线程,所有地址都删除了重复项,但我需要保留重复记录。

import csv
from collections import OrderedDict
import os

cd = os.path.dirname(os.path.abspath(__file__))

fafile = os.path.join(cd, 'MJB_FAScores.csv')
testscores = os.path.join(cd, 'MJB_TestScores.csv')

filenames = fafile, testscores
data = OrderedDict()
fieldnames = []
for filename in filenames:
    with open(filename, 'r') as fp:
        reader = csv.DictReader(fp)
        fieldnames.extend(reader.fieldnames)
        for row in reader:
            data.setdefault(row['Student_Number'], {}).update(row)
fieldnames = list(OrderedDict.fromkeys(fieldnames))
with open('merged.csv', 'w', newline='') as fp:
    writer = csv.writer(fp)
    writer.writerow(fieldnames)
    for row in data.values():
        writer.writerow([row.get(fields, '') for fields in fieldnames])

档案:

Student_Number  Name    Grade   Teacher FA1 FA2 FA3
65731   Ball, Peggy 4   Bauman, Edyn    56  45  98
65731   Ball, Peggy 4   Bauman, Edyn    32  323 232
85250   Ball, Jonathan  3   Clarke, Mary    65  77  45
981235  Ball, David 5   Longo, Noel 56  89  23
91851   Ball, Jeff  0   Delaney, Mary   83  45  42
543 MAX 2   Phil    77  77  77
543 MAX 2   Annie   88  888 88
9844    Lisa    1   Smith, Jennifer 43  44  55

测试分数:

Student_Number  Name    Grade   Teacher MAP Reading MAP Math    FP Level    DSA LN  DSA WW  DSA SJ  DSA DC
65731   Ball, Peggy 4   Bauman, Edyn    175 221 A   54  23  78  99
72941   Ball, Amanda    4   Bauman, Edyn    201 235 J   65  34  65
85250   Ball, Jonathan  3   Clarke, Mary    189 201 L   34  54
981235  Ball, David 5   Longo, Noel 225 231 D   23  55
91851   Ball, Jeff  0   Delaney, Mary   198 175 C
65731   Ball, Peggy 4   Bauman, Edyn    200 76  Y   54  23  78  99
543 MAX 2   Phil    111 111 Z   33  44  55  66
543 MAX 2   Annie   222 222 A   44  55  66  77

当前输出:

Student_Number  Name    Grade   Teacher FA1 FA2 FA3 MAP Reading MAP Math    FP Level    DSA LN  DSA WW  DSA SJ  DSA DC
65731   Ball, Peggy 4   Bauman, Edyn    32  323 232 200 76  Y   54  23  78  99
85250   Ball, Jonathan  3   Clarke, Mary    65  77  45  189 201 L   34  54
981235  Ball, David 5   Longo, Noel 56  89  23  225 231 D   23  55
91851   Ball, Jeff  0   Delaney, Mary   83  45  42  198 175 C
543 MAX 2   Annie   88  888 88  222 222 A   44  55  66  77
72941   Ball, Amanda    4   Bauman, Edyn                201 235 J   65  34  65
9844    Lisa    1   Smith, Jennifer 43  44  55

期望的输出:

Student_Number  Name    Grade   Teacher FA1 FA2 FA3 MAP Reading MAP Math    FP Level    DSA LN  DSA WW  DSA SJ  DSA DC
65731   Ball, Peggy 4   Bauman, Edyn    32  323 232 200 76  Y   54  23  78  99
65731   Ball, Peggy 4   Bauman, Edyn    56  45  98  175 221 A   54  23  78  99
85250   Ball, Jonathan  3   Clarke, Mary    65  77  45  189 201 L   34  54
981235  Ball, David 5   Longo, Noel 56  89  23  225 231 D   23  55
91851   Ball, Jeff  0   Delaney, Mary   83  45  42  198 175 C
543 MAX 2   Annie   88  888 88  222 222 A   44  55  66  77
543 MAX 2   Phil    77  77  77  111 111 Z   33  44  55  66
72941   Ball, Amanda    4   Bauman, Edyn                201 235 J   65  34  65
9844    Lisa    1   Smith, Jennifer 43  44  55

【问题讨论】:

  • 您的代码在data.setdefault(row['Student_Number'], {}).update(row) 行上生成一个KeyError: 'Student_Number'
  • 请说明您希望如何进行合并。例如,每个文件中有两条学生 id 65731 的记录,总共有四条,但在所需的输出中只有两条。为什么四个人都没有被保留?
  • 基本上,testscores 文件中的数据应该水平附加到 Student_Number 上匹配的 fafile 中。每个文件都包含不同的数据集,并尝试将每个学生的所有考试成绩放在一起。有些学生参加了两次考试,或者根本不参加考试,因此每个文件中可能有 0、1 条或更多条记录。最终文件应包含以下列:Student_Number、Name、Grade、Teacher、FA1、FA2、FA3、MAP Reading、Map Math、FP Level、DSA LN、DSA WW、DSA SJ、DSA DC。如果学生在 fafile 中没有记录,但在测试分数中有 2 条记录,则他们应该有 2 行数据,其中“FAx”字段为空
  • 您需要准确描述给定两个具有相同'Student_Number' 键的记录字典如何决定是否合并它们,以及应该如何完成(应该保留什么)从每个)。请edit您的问题并把它放在那里,不是在 cmets 中。
  • 但是不应该有重复的记录,这假设教师输入数据是按照指示进行的。不幸的是,他们没有,我也无法确定不应该保留哪些考试成绩——我只能提供数据。除了该学生可用分数的水平“列表”之外,FA 分数和测试分数之间没有相关性。由校长决定评估学生进步的考试成绩。对于 #65731,只要符合正确的学号,哪个 FA 分数与哪个考试分数相配并不重要。

标签: python python-3.x csv merge


【解决方案1】:

您正在使用OrderedDict 存储两个文件中的学生 ID(键)及其记录(值)。

这有一个微妙的含义:新的 student ID 条目将替换以前文件中旧的重复 student ID dict 条目,因为 dict 键是唯一的。

您可以考虑在从一个文件中读取条目后立即将它们写入 merge 文件。之后dict 被清除,下一个文件用于重新填充 dict。这将有助于避免冲突替换学生ID。

【讨论】:

    【解决方案2】:

    对于您的内部循环,您可以执行以下操作:

    for row in reader:
        new_record = dict(row)
        records = data.setdefault(row['Student_Number'], [])
        for record in records:
            new_record.update(record) # preserve old values
            record = copy.copy(new_record) 
        new_record.update(dict(row)) # to preserve original values
        records.append(new_record)
    

    现在写作时你必须更深入:

    for rows in data.values():
        for row in rows:
            writer.writerow(row)
    

    A 开头添加“导入副本”。我是凭脑子写的,可能需要一些调整。

    基本上这样做是以列表的形式添加另一层,您可以在其中使用新值更新旧值并将更新后的新记录添加到列表末尾(所有收集的数据都放入新记录中)。写作时必须更深一层。

    【讨论】:

      【解决方案3】:

      我个人会使用Pandas 来做类似的事情,特别是DataFrame.append

      首先,您将使用pandas.DataFrame.from_csv('filename') 为两个 CSV 创建一个 DataFrame。

      然后将 DataFrame 附加在一起:myDataFrame.append(otherDataframe)

      最后用to_csv()输出结果。

      把它们放在一起:

      【讨论】:

        猜你喜欢
        • 2012-08-12
        • 1970-01-01
        • 2016-11-21
        • 2020-03-18
        • 1970-01-01
        • 1970-01-01
        • 2019-03-27
        • 2013-04-22
        • 2020-11-22
        相关资源
        最近更新 更多