【问题标题】:Match mutliple columns in CSV; copy value from one CSV to other if equal匹配 CSV 中的多个列;如果相等,将值从一个 CSV 复制到另一个
【发布时间】:2017-10-23 01:01:55
【问题描述】:

我有两个包含重叠信息的文件(csv1 和 csv2);如果有匹配项,我想将列中的值从 csv2 复制到 csv1。

csv1 格式为:

empid, name, org, division, title, country, topic, time-on-topic

csv2 是 csv1 的一种聚合版本,但形式为:

org, country, topic, rating

我想要的结果 new_csv 是:

empid, name, org, division, title, country, topic, time-on-topic, rating

基本上,对于 csv1 和 csv2 之间的任何“国家”和“主题”匹配,将关联的“评级”复制回 csv1 结构到一个新文件 csv3。我很尴尬地承认,我花了很多时间在留言板上搜索有关使用字典、元组和列表的信息,但到目前为止,我只有使用一列作为键才能让它工作。 2列可以作为关键吗?还是我问错了问题?

这是我迄今为止一直在做的,但以“empid”为关键:

with open('csv1.csv', 'r') as f:
    first = {rows[0]: rows[1:] for rows in list(csv.reader(f))}

with open('csv2.csv', 'r') as f:
    for row in csv.reader(f):
        if row[0] in first: # row[0] = url
            first[row[0]].append(row[2])

merged = [(k,) + tuple(v) for k, v in first.items()]

with open('output.csv', 'w') as f:
    csv.writer(f).writerows(merged)

我认为我的问题的症结在于使用两列作为键,但我不确定......而且我可以看到在某些情况下我可能会使用多列作为键。我应该以某种方式连接列来创建键吗?

【问题讨论】:

  • 考虑将 csvs 导入数据集(Stata/SAS、R 数据帧,甚至 Python pandas 数据帧)或数据库(SQLite/MS Access 是文件级 dbms),然后合并/加入这两者以获得新分配的列。不需要循环。

标签: python csv


【解决方案1】:

下面是一些应该做你想做的代码:

COUNTRY_CSV1, TOPIC_CSV = 5, 6

with open('csv1.csv', 'r') as f:
    first = {(rows[COUNTRY_CSV1], rows[TOPIC_CSV1]): 
             rows for rows in list(csv.reader(f))}

COUNTRY_CSV2, TOPIC_CSV2, RATING_CSV2 = 1, 2, 3
with open('csv2.csv', 'r') as f:
    for row in csv.reader(f):
        key = row[COUNTRY_CSV2], row[TOPIC_CSV2]
        first.get(key, []).append(row[RATING_CSV2]

with open('output.csv', 'w') as f:
    csv.writer(f).writerows(first.values())

这个问题的主要逻辑变化是,这里我们使用一个二元组作为键(具体的二元组是国家、主题,根据要求)。

但也有许多其他的清理工作——我们将“关键”部分也保留在值中,而不是拆分然后重新合并行。这种冗余使得写出的代码更加简单。

索引已更改为常量,以便更清楚地了解需要哪些字段。最后,“if”语句已被替换为 get 方法调用,该方法调用返回一个新列表。这似乎是虚假的开销,但它不太可能更慢(甚至可能更快——Python 中的性能很奇怪),但可能不太容易出错。

【讨论】:

  • 谢谢!我从概念上理解并且错误可能是我的,因为我是一个新手,当我尝试运行脚本时,我在第 7 行“列表中的行的行(csv.reader(f)).. ...”知道为什么吗?
【解决方案2】:

根据关于使用数据框的建议,我最终基于 pd.merge() 实现了以下脚本。

df1 = pd.read_csv('csv1.csv')
df2 = pd.read_csv('csv2.csv')
result = pd.merge(df1, df2, on = ['empid', 'name', 'org', 'division', 'title', 'country', 'topic', 'time-on-topic'], how = 'right')
result.to_csv("output.csv")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 2015-11-21
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    相关资源
    最近更新 更多