使用CSV的Python嵌套循环

使用CSV的Python嵌套循环,python,csv,match,Python,Csv,Match,我在尝试匹配一些CSV的数据时遇到了一些麻烦。下面是一些CSV示例,其中包含我使用的数据的基本结构 我试图将CSV 2中A列的值与CSV 1中E列的值进行匹配,如果匹配,则将CSV 1中的行写入新的CSV 代码 with open(CSV1,"r") as f, open(CSV2,"r") as g, open("Match.csv","w",newline='') as h: rdr1 = csv.reader(f) rdr2 = csv.reader(g) wtr

我在尝试匹配一些CSV的数据时遇到了一些麻烦。下面是一些CSV示例,其中包含我使用的数据的基本结构

我试图将CSV 2中A列的值与CSV 1中E列的值进行匹配,如果匹配,则将CSV 1中的行写入新的CSV

代码

with open(CSV1,"r") as f, open(CSV2,"r") as g, open("Match.csv","w",newline='') as h:
    rdr1 = csv.reader(f)
    rdr2 = csv.reader(g)
    wtr = csv.writer(h)
    for r in rdr1:
        for s in rdr2: 
            if (s[0] == r[4]):
                print("match")
我使用的数据集有100000行,因此有更多的匹配,并且匹配会重复几次。在本例中,只有一次匹配两次(92)

在我的代码中,我假设我正在循环第一个CSV中的所有行,对于每一行,我在循环第二个CSV中的所有行。如果值相等,则打印“匹配”

我的问题是,它最多只打印一次“匹配”。我已经试着去想了,但是我在这一点上被卡住了。控制台不应该每次值s[0]等于r[4]时都打印“匹配”吗?在本例中,这种情况会发生多次

我希望确保每次有匹配项时,编写器都会在我的输出CSV中写入一个新行,但是我只得到第一个匹配项。救命啊

CSV 1

A   B       C           D           E
A   Test1   0.101534549 0.590695315 95
B   Test2   0.8264073   0.120144407 44
C   Test3   0.977242848 0.067444475 97
D   Test4   0.270980415 0.524929719 62
E   Test5   0.059128388 0.260576647 36
F   Test6   0.571208391 0.246145371 85
G   Test7   0.098088188 0.618968191 91
H   Test8   0.898575649 0.56778217  88
I   Test9   0.233745198 0.514747763 2
J   Test10  0.452100086 0.749702553 97
K   Test11  0.493666064 0.002437728 80
L   Test12  0.052633239 0.864048743 22
M   Test13  0.635517951 0.716967917 21
N   Test14  0.921723813 0.766473275 22
O   Test15  0.54634609  0.853116802 92
P   Test16  0.400754273 0.993727094 61
Q   Test17  0.549368986 0.868975583 46
R   Test18  0.301279637 0.222360597 65
S   Test19  0.152111468 0.698786954 1
T   Test20  0.313768676 0.354556772 21
CSV 2

A
29
7
52
66
27
91
27
33
84
85
41
92
80
22
15
61
62
17
21
92

像这样的方法应该会奏效:

with open(CSV1, 'r') as f, open(CSV2, 'r') as g, open('Match.csv', 'w', newline='') as h:
    rdr1 = csv.reader(f)
    rdr2 = csv.reader(g)
    wtr = csv.writer(h)

    # build up a set of everything in CSV2
    haystack = set()
    for i, line in enumerate(rdr2):
        if i == 0:
            continue # skip header line
        haystack.add(line[0])

    # check each line for a match in our set
    for line in rdr1:
        needle = line[4]
        if needle in haystack:
            wtr.writerow(line)
它保持与您所做的相同的基本思想,但是将一个完整的文件读入一个集合(名为haystack),然后我们检查目标单元格(名为Pineder)的成员资格


正如Shiva和一些评论者所指出的,问题在于
g
的文件指针没有在每次新的迭代中重置到开头。此解决方案通过只读取一次文件来避免倒带。

类似的方法应该可以:

with open(CSV1, 'r') as f, open(CSV2, 'r') as g, open('Match.csv', 'w', newline='') as h:
    rdr1 = csv.reader(f)
    rdr2 = csv.reader(g)
    wtr = csv.writer(h)

    # build up a set of everything in CSV2
    haystack = set()
    for i, line in enumerate(rdr2):
        if i == 0:
            continue # skip header line
        haystack.add(line[0])

    # check each line for a match in our set
    for line in rdr1:
        needle = line[4]
        if needle in haystack:
            wtr.writerow(line)
它保持与您所做的相同的基本思想,但是将一个完整的文件读入一个集合(名为haystack),然后我们检查目标单元格(名为Pineder)的成员资格


正如Shiva和一些评论者所指出的,问题在于
g
的文件指针没有在每次新的迭代中重置到开头。此解决方案通过只读取一次文件来避免倒带。

代码中的错误是,
g
需要在每个循环中倒带回文件的开头,并且每次倒带时都需要调用
csv\u reader
。像这样:

for r in rdr1:
    g.seek(0)          # seek to the beginning of the file
    s = csv.reader(g)  # restart iterator
    for s in rdr2:
        if s[0] == r[4]:
            print("match")
with open(CSV1) as f, open(CSV2) as g, open('foo-match.csv', 'w') as h:
    lines1 = [line.split(',') for line in f]
    lines2 = [line.split(',') for line in g]
    commonlineindices = [i1 for (i1, row1) in enumerate(lines1) for row2 in lines2 if row1[4]==row2[0]]
    print(commonlineindices)
    h.writelines([','.join(lines1[index]) for index in commonlineindices])
与每次都必须倒回文件开头(这可能是一个昂贵的操作)相比,一个更快的解决方案是将所有行读入局部变量,然后使用列表理解执行类似“交叉”的集合。像这样:

for r in rdr1:
    g.seek(0)          # seek to the beginning of the file
    s = csv.reader(g)  # restart iterator
    for s in rdr2:
        if s[0] == r[4]:
            print("match")
with open(CSV1) as f, open(CSV2) as g, open('foo-match.csv', 'w') as h:
    lines1 = [line.split(',') for line in f]
    lines2 = [line.split(',') for line in g]
    commonlineindices = [i1 for (i1, row1) in enumerate(lines1) for row2 in lines2 if row1[4]==row2[0]]
    print(commonlineindices)
    h.writelines([','.join(lines1[index]) for index in commonlineindices])

这将计算所需行的索引。一旦有了这个,就可以直接打印出相应的行。

代码中的错误是,
g
需要在每个循环中倒回文件的开头,并且每次倒回时都需要调用
csv\u reader
。像这样:

for r in rdr1:
    g.seek(0)          # seek to the beginning of the file
    s = csv.reader(g)  # restart iterator
    for s in rdr2:
        if s[0] == r[4]:
            print("match")
with open(CSV1) as f, open(CSV2) as g, open('foo-match.csv', 'w') as h:
    lines1 = [line.split(',') for line in f]
    lines2 = [line.split(',') for line in g]
    commonlineindices = [i1 for (i1, row1) in enumerate(lines1) for row2 in lines2 if row1[4]==row2[0]]
    print(commonlineindices)
    h.writelines([','.join(lines1[index]) for index in commonlineindices])
与每次都必须倒回文件开头(这可能是一个昂贵的操作)相比,一个更快的解决方案是将所有行读入局部变量,然后使用列表理解执行类似“交叉”的集合。像这样:

for r in rdr1:
    g.seek(0)          # seek to the beginning of the file
    s = csv.reader(g)  # restart iterator
    for s in rdr2:
        if s[0] == r[4]:
            print("match")
with open(CSV1) as f, open(CSV2) as g, open('foo-match.csv', 'w') as h:
    lines1 = [line.split(',') for line in f]
    lines2 = [line.split(',') for line in g]
    commonlineindices = [i1 for (i1, row1) in enumerate(lines1) for row2 in lines2 if row1[4]==row2[0]]
    print(commonlineindices)
    h.writelines([','.join(lines1[index]) for index in commonlineindices])

这将计算所需行的索引。一旦你有了这个,就可以直接打印出相应的行。

你为什么不使用
pandas
来执行内部连接,然后写入csv?我从来没有使用过pandas。我来看看问题是rdr1和rdr2是迭代器,rdr2已经耗尽了,因为您在rdr2的第一次迭代中完全迭代了它。但是,是的,使用熊猫。好的,我会调查的。一周前刚开始使用python进行数据分析,所以对我来说是全新的。谢谢有什么理由不使用熊猫来执行内部连接,然后写入csv?我从来没有使用过熊猫。我来看看问题是rdr1和rdr2是迭代器,rdr2已经耗尽了,因为您在rdr2的第一次迭代中完全迭代了它。但是,是的,使用熊猫。好的,我会调查的。一周前刚开始使用python进行数据分析,所以对我来说是全新的。谢谢完成!这是我问的第一个问题,所以我是新手!NP很高兴能帮忙:)完成了!这是我问的第一个问题,所以我是新手!NP我很乐意帮忙:)