如何优化搜索和比较熊猫中的行?

时间:2019-07-15 07:40:24

标签: python pandas dataframe

我有两个df。基数是10万行,嗅探是54k行。

这是dfs的结构:

基础:

SampleNum SampleIdInt   SecondName
  1         ASA2123313  A2123313
  2         ARR4112234  R4112234
  3         AFG4234122  G4234122
  4         GGF412233   F412233
  5         GTF423512   F423512
  6         POL23523552 L23523552
...

这是Snps df:

   SampleNum SampleIdInt
      1         ART2114155
      2         KWW4112234
      3         AFG4234122 
      4         GGR9999999
      5         YUU33434324
      6         POL23523552
    ...

现在来看例如Snps和base中的第二行。它们具有相同的数字(前三个字符现在对我来说并不重要)。

因此,我创建了一个commonlist,其中包含来自snsp的数字,这些数字也出现在base中。在dfs之间所有具有相同编号的行。 (长度通常为15k)

common_list = [4112234, 4234122, 23523552]

现在我要创建三个新列表。

confirmedSnps =其中整个SampleIdInt与基数相同。在此示例中:AFG4234122。为此,我确信secondName是正确的。

un_comfirmedSnpS =我的数字不错,但前三个字符不同。示例:KWW4112234中的SnpS和base中的ARR4112234。在这种情况下,我不确定SecondName是否正确,因此我需要稍后进行检查。

最后一个moreThanOne列表。该列表应追加所有重复的行。例如,如果在基地我将拥有KWW4112234和AFG4112234,则两者都应转到该列表。

我写了一个代码。工作正常,但问题是时间。我过滤了15k个元素,每个元素处理4秒。这意味着整个循环将运行17小时! 我在优化该代码方面寻求帮助。

那是我的代码:

comfirmedSnps = []
un_comfirmedSnps = []
moreThanOne = []
for i in range(len(common)):
    testa = baza[baza['SampleIdInt'].str.contains(common[i])]
    testa = testa.SampleIdInt.unique()
    print("StepOne")
    testb = snps[snps['SampleIdInt'].str.contains(common[i])]
    testb = testb.SampleIdInt.unique()
    print("StepTwo") 
    if len(testa) == 1 and len(testb) == 1:
        if (testa == testb) == True:
            comfirmedSnps.append(testb)
        else:
            un_comfirmedSnps.append(testb)        
    else:
        print("testa has more than one contains records. ")
        moreThanOne.append(testb)
    print("StepTHREE")
    print(i,"/", range(len(common)))

我添加了一个“步骤”打印,以检查大部分时间花费在哪一部分上。它是StepOnestepTwo之间的代码。第一步和第三步正在运行。

有人可以帮助我处理该案吗?可以肯定的是,大多数U会找到更好的解决方案。

1 个答案:

答案 0 :(得分:0)

您尝试做的事情通常被称为join,在大熊猫中,这令人讨厌的被称为merge。只需处理三个首字母中的小麻烦,但这很容易:

snps.numeric_id = snps.SampleIdInt.apply(lambda s: s[3:])
base.numeric_id = base.SampleIdInt.apply(lambda s: s[3:])

现在您可以计算三个数据帧:

confirmed = snps.merge(base, on='SampleIdInt')
unconfirmed = snps.merge(
    base, on='numeric_id'
).filter(
    lambda r.SampleIdInt_x != r.SampleIdInt_y
)
more_than_one = snps.group_by('numeric_id').filter(lambda g: len(g) > 1)

我敢打赌这行不通,但希望您能明白。