[英]Python - Nested Loops with CSVs
尝试匹配某些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")
我正在使用具有100,000行的数据集,因此存在更多匹配项,并且匹配项重复了几次。 在此示例中,只有两次匹配的情况(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)中,然后我们检查该文件是否为目标单元(名为needle)的成员身份。
正如Shiva和一些评论者所指出的那样,问题在于g
的文件指针没有在每次新迭代时都重置为开始。 此解决方案通过仅读取一次文件来回退。
代码中的错误是,在每个循环中, g
必须退回到文件的开头,并且每次倒带时都需要对其调用csv_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])
这将计算所需的行的索引。 一旦有了这个,就可以直接打印出相应的行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.