如果第一列相同,则组合两个csv文件

时间:2016-01-08 21:31:23

标签: python csv

我有两个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循环存在问题。这可能是一个简单的解决方案,但我现在没有看到我的错误。

2 个答案:

答案 0 :(得分:1)

你可以使用熊猫 - 它是一个功能强大的数据操作库。首先,将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中的第一列),因此我们只选择您需要的列来创建新数据框:

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

答案 1 :(得分: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