【问题标题】:Optimizing searches in very large csv files在非常大的 csv 文件中优化搜索
【发布时间】:2019-12-20 05:31:21
【问题描述】:

我有一个单列的 csv 文件,但有 620 万行,所有行都包含 6 到 20 个字母之间的字符串。一些字符串会在重复(或更多)条目中找到,我想将它们写入一个新的 csv 文件 - 猜测应该有大约 100 万个非唯一字符串。就是这样,真的。但是,不断搜索包含 600 万个条目的字典确实需要时间,我会很感激有关如何做到这一点的任何提示。根据我所做的一些时间安排,到目前为止,我编写的任何脚本都需要至少一周 (!) 才能运行。

第一次尝试:

in_file_1 = open('UniProt Trypsinome (full).csv','r')
in_list_1 = list(csv.reader(in_file_1))
out_file_1 = open('UniProt Non-Unique Reference Trypsinome.csv','w+')
out_file_2 = open('UniProt Unique Trypsin Peptides.csv','w+')
writer_1 = csv.writer(out_file_1)
writer_2 = csv.writer(out_file_2)

# Create trypsinome dictionary construct
ref_dict = {}
for row in range(len(in_list_1)):
    ref_dict[row] = in_list_1[row]

# Find unique/non-unique peptides from trypsinome
Peptide_list = []
Uniques = []
for n in range(len(in_list_1)):
    Peptide = ref_dict.pop(n)
    if Peptide in ref_dict.values(): # Non-unique peptides
        Peptide_list.append(Peptide)
    else:
        Uniques.append(Peptide) # Unique peptides

for m in range(len(Peptide_list)):
    Write_list = (str(Peptide_list[m]).replace("'","").replace("[",'').replace("]",''),'')
    writer_1.writerow(Write_list)

第二次尝试:

in_file_1 = open('UniProt Trypsinome (full).csv','r')
in_list_1 = list(csv.reader(in_file_1))
out_file_1 = open('UniProt Non-Unique Reference Trypsinome.csv','w+')
writer_1 = csv.writer(out_file_1)

ref_dict = {}
for row in range(len(in_list_1)):
    Peptide = in_list_1[row]
    if Peptide in ref_dict.values():
        write = (in_list_1[row],'')
        writer_1.writerow(write)
    else:
        ref_dict[row] = in_list_1[row]

编辑:这是 csv 文件中的几行:

SELVQK
AKLAEQAER
AKLAEQAERR
LAEQAER
LAEQAERYDDMAAAMK
LAEQAERYDDMAAAMKK
MTMDKSELVQK
YDDMAAAMKAVTEQGHELSNEER
YDDMAAAMKAVTEQGHELSNEERR

【问题讨论】:

  • 请张贴一些典型的 csv 行。
  • 问题是您一次读取整个文件,这对任何人都不利。如果只需要输出重复的行,uniq -Di somefile.txt > duplicate_lines.txt
  • 奇怪的逗号分隔值(csv),没有什么可以分隔的,呵呵!我不会认为这是一个 csv 文件。

标签: python optimization csv


【解决方案1】:

用 Numpy 来做。大致:

import numpy as np
column = 42
mat = np.loadtxt("thefile", dtype=[TODO])
uniq = set(np.unique(mat[:,column]))
for row in mat:
    if row[column] not in uniq:
        print row

您甚至可以使用 numpy.savetxt 和 char-array 运算符对输出阶段进行矢量化处理,但这可能不会有太大的不同。

【讨论】:

    【解决方案2】:

    第一个提示:Python 支持惰性求值,最好在处理大型数据集时使用它。所以:

    • 迭代您的 csv.reader,而不是构建一个巨大的内存列表,
    • 不要使用范围构建庞大的内存列表 - 如果您需要项目和索引,请改用 enumerate(seq),如果不需要索引,只需迭代序列的项目。

    第二个提示:使用dict(哈希表)的主要目的是查找,而不是值...所以不要构建用作列表的巨大字典。

    第三个提示:如果您只是想要一种存储“已经看到”值的方法,请使用Set

    【讨论】:

    • 谢谢!使用集合并在阅读器上进行迭代确实可以很好地加快速度 - 脚本现在需要大约一分钟才能运行。不过,我很想知道为什么/如何这样快得多。它不仅快一点,而且令人难以置信!
    • 第一个明显的原因:您使用 dict 的方式(主要:作为数组)意味着 O(n) 查找时间(并且具有非常大的 'n' 值)。使用一个集合你有 O(1) 的查找时间。第二个可能的原因(但这是疯狂的猜测):由于您的数据集的大小有两个数据的内存副本(列表然后是字典)可能已经吃掉了所有可用的 RAM 并迫使您的计算机使用交换,这非常慢.
    • 好的,这就清楚了!
    【解决方案3】:

    我的 Python 不太好,所以我不知道“in”是如何工作的,但你的算法似乎在 n² 中运行。 尝试在阅读列表后对其进行排序,使用 n log(n) 中的算法,如快速排序,它应该会更好。 列表排序后,您只需检查列表的两个连续元素是否相同。

    所以你得到了 n 中的读数,n log(n) 中的排序(最多),以及 n 中的比较。

    【讨论】:

      【解决方案4】:

      虽然我认为 numpy 解决方案是最好的,但我很好奇我们是否可以加快给定示例的速度。我的建议是:

      • 跳过 csv.reader 费用,只需阅读该行
      • rb 跳过修复换行符所需的额外扫描
      • 使用更大的文件缓冲区大小(读​​取 1Meg,写入 64K 可能不错)
      • 使用 dict 键作为索引 - 键查找比值查找快得多

      我不是一个麻木的人,所以我会做类似的事情

      in_file_1 = open('UniProt Trypsinome (full).csv','rb', 1048576)
      out_file_1 = open('UniProt Non-Unique Reference Trypsinome.csv','w+', 65536)
      
      ref_dict = {}
      for line in in_file_1:
          peptide = line.rstrip()
          if peptide in ref_dict:
              out_file_1.write(peptide + '\n')
          else:
              ref_dict[peptide] = None
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-24
        • 1970-01-01
        • 1970-01-01
        • 2020-12-14
        • 2015-07-04
        • 1970-01-01
        • 2013-05-07
        相关资源
        最近更新 更多