我有两个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)))
我添加了一个“步骤”打印,以检查大部分时间花费在哪一部分上。它是StepOne
和stepTwo
之间的代码。第一步和第三步正在运行。
有人可以帮助我处理该案吗?可以肯定的是,大多数U会找到更好的解决方案。
答案 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)
我敢打赌这行不通,但希望您能明白。