比较两个csv文件以输出匹配的Python

时间:2015-01-16 19:56:21

标签: python list csv compare match

我有一个名为“organs.csv”的csv文件和另一个包含大量数据的csv文件。我正在比较它们以获得它们之间的匹配。后一个文件没有任何特定的格式,所以我不知道哪个列有关于器官的数据。我已经尝试了下面的代码来获得匹配,但它有两个问题。

  1. 如果csv2在两列中有一个器官,它会在列表中追加两次。
  2. 如果一行没有任何器官,它就会忽略它。
  3. 我希望它能够做到以下几点:

    1. 如果行有器官,请跳到下一行(每行限制一个器官)
    2. 如果未找到器官,请打印“ - ”
    3. 之类的内容

      代码:

      import csv
      filename = "file.csv"
      complist, orglist = [], []
      fileA = open(filename, "rb")
      reader = csv.reader(fileA, delimiter=',')
      for row in reader:
          for row_str in row:
              complist.append(row_str)
      with open("organs.csv", "rb") as fileB:
          reader = csv.reader(fileB, delimiter='\n')
          for row in reader:
              orglist += row
              orglist = [x.lower() for x in orglist]
      org = open ("organ_matches.txt", "wb")
      org_writer = csv.writer(org)
      for s in complist:
          for xs in orglist:
              if xs in s:
                  print >> org, xs
      org.close()
      orgfile = open ("organ_matches.txt" , "r")
      organ = orgfile.read()
      organ = organ.split("\n")
      organ = ",".join (organ)
      organ = organ.split(",")
      orgfile.close()
      print organ
      

      csv1:

      forearm
      leg
      abdomen
      

      CSV2:

      h1,h2,h3,h4
      data1,forearm biopsy,tissue,cell
      data2,leg injury,tissue in leg,cell9
      data4,data,tissue4,cell6
      

      现在打印:

      ['forearm','leg','leg']
      

      期望的输出:

      ['forearm','leg','-']
      

3 个答案:

答案 0 :(得分:2)

这里我最终使用列表理解 *来存储器官名称, 接下来我循环了另一个文件的第二行到最后一行, 使用stop辅助变量一次退出两个循环 (这是你没有抓到的......)。

代码MkI

organs = [line.strip() for line in file('uno.csv')]
matches = []
for line in [line for line in file('due.csv')][1:]:
    stop = 0
    matches.append('-')
    for item in line.split(','):
        if stop : break
        for organ in organs:
            if organ in item:
                matches[-1] = organ
                stop = 1

print matches

Alternate Take

在这里,我删除了不太优雅的辅助变量并使用了一些技巧, 更晦涩但更愉快(对我而言)的方法

organs = [line.strip() for line in file('uno.csv')]

matches = []
for line in [line for line in file('due.csv')][1:]:
    match = '-'
    for item in line.split(','):
        if match != '-' : break
        for organ in organs:
            if organ in item:
                match = organ
    matches.append(match)

print matches

输出

['forearm', 'leg', '-']

* 编辑似乎organs的顺序对您很重要,所以我更改了用于存储器官名称的数据结构一个清单。


编辑#2

更准确

从OP可以清楚地看出,对于due.csv的每一行,只需要一个匹配。我不清楚(回想起来)是如何只选择一场比赛。

我认为我们要从左到右扫描每个item中的line,并在找到匹配时停止扫描,到目前为止一切都很好......但如果{{{ 1}}匹配多个item

我当前的代码始终完成organ上的for循环,因此附加的匹配是organs中定义的顺序中的最后一个匹配...

如果请求的匹配是第一个,则必须修改我的代码,将uno.csv添加到break上的for循环

organs

那就是说,选择权是你的......

答案 1 :(得分:1)

以下代码通常有效,忽略了csv2的标题行:

import csv
orglist = []
organ_matches = []

# Generate list of organs
with open('organs.csv', 'rb') as f_org:

    csv_f = csv.reader(f_org)

    for row in csv_f:
        orglist.append(row[0])

# Convert to a set
set_org = set(orglist)

# Read csv2 file
with open('file.csv', 'rb') as f_tbl:

    # Open output file to write to
    with open('organ_matches.txt', 'wb') as f_out:

        csv_f = csv.reader(f_tbl)
        csv_f.next() # Ignore header

        for row in csv_f:

            set_row = set(' '.join(row).split(' ')) # Combine list elements and separate words

            # Find common words with organs list and select only one
            if set_row.intersection(set_org):
                organ_match = list(set_row.intersection(set_org))[0]
            else:
                organ_match = '-'

            organ_matches.append(organ_match)
            f_out.write(organ_match + '\n')

答案 2 :(得分:0)

您只需要遍历数据文件(complist)一次,并且可以删除额外的嵌套循环。

这样你的:



for s in complist:
    for xs in orglist:
        if xs in s:
            print >> org, xs




变为:



for s in complist:
    if s in orglist:
        print >> org, s
    else:
        print >> org, '-'