如果第一列相同,如何合并两个CSV文件

3

我是一名有用的助手,可以为您翻译文本。

我有两个csv文件,长这样:

第一个文件:

143, m, 933, gt, mr
129, f, 945, se, tk
267, f, 234, kl, tk
122, t, 586, gt, zi

第二个文件:
143, 533
876, 676
122, 221
231, 879  

现在我想要合并所有行中特定的列,其中第一个文件中的数字与第二个文件中的数字相同。处理后的示例如下:
143, gt, mr, 533
122, gt, zi, 221

因为我想将文件1中的列034与文件2中的列1相结合,如果第一列中的数字相同(在这种情况下是143122)。两个文件中都有约3000行,其中许多行的第一列数字相同,因此我希望所有匹配的结果都写入一个结果文件。以下是我的代码:

def combiner(file 1, file 2, result_file):
    with open(file 1,"rb") as f1, open(file 2,"rb") as f2, open(result_file,"wb") as result:
        rdr1= csv.reader(f1)
        rdr2= csv.reader(f2)
        wtr= csv.writer(result)
        for row1 in rdr1:
            for row2 in rdr2:
                if row2[0] == row1[0]:
                    wtr.writerow((row2[0], row2[3], row2[4], row1[1]))

如果我运行程序,它只能在第一行工作,但之后就停止了。应用于这个例子,我只会得到


143, gt, mr, 533

在我的结果文件中写下了这段内容。我认为for循环存在问题。可能是一个简单的解决方案,但我目前没有看到自己的错误。


你要做的是所谓的“内连接”。如果你需要做很多这样的操作,可以考虑使用 pandas 包。使用 pandas 只需要3行代码即可完成。 - JBGreen
2个回答

1
你可以使用pandas - 这是一个强大的数据操作库。首先,将csv文件加载到数据框中。
import pandas as pd

df1 = pd.read_csv('file1.csv', header=None, index_col=0)
df2 = pd.read_csv('file2.csv', header=None, index_col=0)

你为两个文件都设置了 index_col=0,因为你要在每个文件的第一列上进行连接——默认情况下,连接是在索引上进行的。

df_joined = df1.join(df2, how='inner', rsuffix='f2')

“内部”连接仅保留两个文件中都存在的行。df_joined将具有所有列(file1的4列加上file2的2列)。

rsuffix表示如果存在列名冲突,则file2中的列将添加后缀“f2”。由于我们没有定义列名,它们将默认分配数字(1、2、3等)。由于file2中的第1列和第2列与file1中的第1列和第2列冲突,因此它们将分别命名为1f2和2f2。

根据您的问题,您只需要其中一些列(第3列和第4列以及file2的第1列),因此我们通过仅选择所需的列来创建一个新的数据框:

df_out = df_joined[[3, 4, '1f2']]
df_out.to_csv('file_out.csv', header=False)

0

你的问题

csv.reader 对象是一个迭代器。当你循环遍历它时:

>>> rdr1 = csv.reader(open('file_1.txt'))
>>> for x in reader:
        print(x)
    ['143', ' m', ' 933', ' gt', ' mr']
    ['129', ' f', ' 945', ' se', ' tk']
    ['267', ' f', ' 234', ' kl', ' tk']
    ['122', ' t', ' 586', ' gt', ' zi']

你消耗了它。下次循环时,就没有什么了:

>>> for x in reader:
         print(x)

你可以将你的读者转换成列表:
>>> rdr1= list(csv.reader(open('file_1.txt'))

这应该可以工作。

更好的解决方案

循环遍历文件一中的所有行,对于每个外部循环遍历文件二中的所有行是低效的。这将更有效率。

使用第一列作为键将两个文件都读入字典:

import csv

def read_file(fobj):
    data = {}
    for line in csv.reader(fobj):
        data[line[0]] = line[1:]
    return data

with open('file_1.txt') as f1, open('file_2.txt') as f2:
    data1 = read_file(f1)
    data2 = read_file(f2)

遍历文件一中的所有键,并从文件一和文件二中选择数据进行写出:

with open('res.txt', 'w') as result:
    wtr= csv.writer(result)
    for key in data1.keys():
        try:
            wtr.writerow((key, data1[key][2], data1[key][3], data2[key][0]))
        except KeyError:
            pass

内容或res.txt

143, gt, mr, 533
122, gt, zi, 221

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接