【问题标题】:Compare entries in columns from CSV files and extract matched - python比较 CSV 文件中的列中的条目并提取匹配的 - python
【发布时间】:2012-02-28 03:19:59
【问题描述】:

我有两个 CSV 文件(三列),我需要比较它们并从其他匹配的文件(五列)中提取行。文件示例如下:

文件1:

ATGCGCGACAGT, ch3, 123546
ATGCATACAGGATAT, ch2, 5141561615

......等等大约 100 个条目

文件2:

ATGCGGCGACAGT,ch3, 123456,mi141515, AUCAGCUAUAUAU, UACGCAGAUAUAUA
ATCAGACGATTATGA, ch4, 4564764, mi653453, AUCAGCAAUUUUCG, AUACAGACAAAAA

....等大约 50000 个条目

我需要匹配这两个文件的第 1,2 列和第 3 列,使 file1 的所有三列都应与 file2 匹配。如果发生这种情况,则提取 4,5 和 6 列进行进一步处理。

我在想:

fhout=csv.writer(open('parsed_out', 'w'), delimiter=',')

for i in file1:

     a=[0]
     b=[1]
     c=[2]
      for x in file2:
       d=[0]
       e=[1]
       f=[2]
       g=[3]
       h=[4]
       i=[5]
         if a==d and b==e and c==f:
           fhout.writerow([g]+[h]+[i])
         else:
           pass

但有人告诉我,我可以使用散列或其他更好的方法,而不是为 file1 中的 10,000 个或更多条目编写如此大的循环

请建议我更好的方法来实现这一点。文件 1 和文件 2 都是从更复杂的文件中解析出来的。

【问题讨论】:

  • 您可以尝试将数据加载到一些 sqlite 表中,然后将它们加入您想要的列中。

标签: python csv compare hash


【解决方案1】:

下面按照您的建议使用对第一个文件的集合理解创建一个哈希:

S = {tuple(line) for line in csv.reader(File1)}

然后在读取第二个文件时,查找速度要快得多。

for line in csv.reader(File2):
    key = tuple(line[:3])
    if key in S:
        print(line)

【讨论】:

    【解决方案2】:

    尝试类似:

    import csv
    
    file_1_tuples = []
    
    with open("file_1.csv") as fh:
        csv_reader = csv.reader ( fh )
        for row in csv_reader:
            file_1_tuples.append(  tuple(row)  )
    
    with open("file_2.csv") as fh:
        csv_reader = csv.reader ( fh )
        for row in csv_reader:
            if tuple(row[0:3]) in file_1_tuples:
                print ( row[3:6] )
    

    使用以下数据运行时:

    file_1.csv

    person, john, smith
    person, anne, frank
    person, bob, macdonald
    fruit, orange, banana
    fruit, strawberry, fields
    fruit, ringring, banana
    

    file_2.csv

    person, john, smith, 1, 2, 3
    person, anne, frank, 4, 5, 6
    person, bob, macdonald, 7, 8, 9
    

    它产生输出

    [' 1', ' 2', ' 3']
    [' 4', ' 5', ' 6']
    [' 7', ' 8', ' 9']
    

    编辑:使用集合和列表推导的更好的实现:

    import csv, pprint
    
    with open("file_1.csv") as fh:
        csv_reader = csv.reader ( fh )
        file_1_tuples = { tuple(row) for row in csv_reader }
    
    with open("file_2.csv") as fh:
        csv_reader = csv.reader ( fh )
        matched_rows = [ row for row in csv_reader if (tuple(row[:3]) in file_1_tuples)]
    
    pprint.pprint (matched_rows)
    

    编辑 2: 请注意,此实现对 CSV 文件中的空格很敏感。如果 CSV 文件中的间距不一致,请使用 row = [element.strip(' ') for element in row] 之类的内容去除所有空格。

    【讨论】:

    • 为什么在file2中一个元组是从0-3组成的来匹配file_1_tuples?不应该是0-2吗?这是文件 2 的前三个元素与文件 1 中的元组匹配。
    • @AtulKakrana : 在 Python 中对数组进行切片时,包含起始索引但 不包含结束索引。 即对于 a = [10, 20, 30, 40, 50, 60]a[0:2] 仅给出 [10,20] . a[0:3]a[:3] 将给出前三个元素 [10,20,30]
    【解决方案3】:

    将文件 1 中的字段放在一个元组中,然后将每个元组添加到一个集合中。然后,您可以对场景中文件 2 中的前三个字段执行包含测试,这比您假设的实现要快得多。

    【讨论】:

    • @Abrahms:感谢您的帮助。你能详细说明一下吗? File1:一行的所有三个字段组成一个元组。之后我就没有追了。我的编程水平最好用初学者来形容。
    • 当您解析一行时,格式为[a, b, c],即list。将其传递给tuple 构造函数会将其转换为tuplesometuple = tuple(somelist)
    • 查看我对@IgnacioVazquez-Abrams 想法实施的回答。 (使用列表而不是可能更有效的集合,但你明白了。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2022-01-23
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    相关资源
    最近更新 更多