python - 如何提高 np.where 的性能(在 line_profiler 中占用 98% 的时间)
问题描述
我正在使用 np.where 搜索从大型数据帧中的文件读取的值,这需要 98% 的时间。代码运行大约需要 19 小时。
因此,此代码扫描包含 2 列约 50 万条记录的数据框,第一列包含数字,第二列包含文本。现在的工作流程是我逐行读取另一个文件,然后在数据框中搜索“alleleID”,并在匹配后从数据框中提取一些数据。我正在使用 np.where 代码执行此操作。
res = np.where(df['alleleID'] == alist[0])
这条线在 line_profiler 中大约占 98%。那么,我该如何改进呢?
经过研究,我在索引后尝试了 df.loc 但我发现的问题是,每次我搜索从文件中读取的一个等位基因 ID 并且它位于变量 (alist[0]) 中时,我无法将此变量传递给使用搜索
res = df.loc(alist[0])
因为 df.loc 总是期望一个值而不是一个变量。
将不胜感激任何帮助,以提高该程序的性能。谢谢你。完整代码如下:
with open('C:/Data/DATA/ClinVar/temp.dat', 'r') as varFile:
count = 0
dat1 = []
dat2 = []
dat3 = []
dat4 = []
dat5 = []
dat6 = []
dat7 = []
dat8 = []
dat9 = []
dat10 = []
dat11 = []
dat12 = []
dat13 = []
dat14 = []
dat15 = []
dat16 = []
dat17 = []
dat18 = []
dat19 = []
dat20 = []
dat21 = []
dat22 = []
dat23 = []
dat24 = []
dat25 = []
dat26 = []
dat27 = []
dat28 = []
dat29 = []
dat30 = []
dat31 = []
dat32 = []
dat33 = []
dat34 = []
dat35 = []
dat36 = []
dat37 = []
dat38 = []
dat39 = []
dat40 = []
for line in varFile:
alist = line.split('\t')
count += 1
print(alist[0], "-", count)
if(alist[1] == 'single nucleotide variant'):
hgvs = '-'
aaChange = ''
otherID = '-'
otherID1 = '-'
uniProt = ''
uniProt_var = ''
omim_list = ''
if alist[2] and not alist[2].isspace():
hgvs = alist[2].split(' ')
i = 0
for i in range(0,len(hgvs)):
if(hgvs[i][0] == "("):
aaChange = hgvs[i]
else:
hgvs = '-'
otherID = alist[28].split(',')
j = 0
omim = ''
uniprot = ''
hgmd = ''
hbvar_list = ''
uni_list = ''
hgmd_list = ''
flag1 = 0
flag2 = 0
flag3 = 0
flag4 = 0
flag5 = 0
indices1 = [i for i, elem in enumerate(otherID) if 'OMIM' in elem]
for b in range(0, len(indices1)):
omim = otherID[indices1[b]].split(':')
flag2 += 1
if(flag2 == 2):
omim_list = omim_list+','+omim[1]
#print("OMIM_list",omim_list)
else:
omim_list = omim[1]
indices2 = [i for i, elem in enumerate(otherID) if 'HGMD' in elem]
for b in range(0, len(indices2)):
hgmd = otherID[indices2[b]].split(':')
flag3 += 1
if(flag3 == 2):
hgmd_list = hgmd_list+','+hgmd[1]
else:
hgmd_list = hgmd[1]
indices3 = [i for i, elem in enumerate(otherID) if 'HBVAR' in elem]
for b in range(0, len(indices3)):
hbvar = otherID[indices3[b]].split(':')
flag4 += 1
if(flag4 == 2):
hbvar_list = hbvar_list+','+hbvar[1]
else:
hbvar_list = hbvar[1]
indices4 = [i for i, elem in enumerate(otherID) if 'UniProtKB' in elem]
for b in range(0, len(indices4)):
otherID1 = otherID[indices4[b]].split(':')
flag5 += 1
if(flag5 == 2):
uni_list = uni_list+','+otherID1[1]
else:
uni_list = otherID1[1]
AF_ESP = ''
AF_EXAC = ''
AF_TGP = ''
res = np.where(df['alleleID'] == alist[0])
if res[0].size != 0:
res1 = df['info'][res[0][0]].split(';')
indices5 = [i for i, elem in enumerate(res1) if 'AF_ESP' in elem]
for b in range(0, len(indices5)):
res2 = res1[indices5[b]].split('=')
AF_ESP = res2[1]
indices6 = [i for i, elem in enumerate(res1) if 'AF_EXAC' in elem]
for b in range(0, len(indices6)):
res2 = res1[indices6[b]].split('=')
AF_EXAC = res2[1]
indices7 = [i for i, elem in enumerate(res1) if 'AF_TGP' in elem]
for b in range(0, len(indices7)):
res2 = res1[indices7[b]].split('=')
AF_TGP = res2[1]
alist[30] = alist[30].rstrip('\n')
dat1.append(alist[0])
dat2.append(alist[1])
dat3.append(alist[2])
dat4.append(hgvs[0])
dat5.append(aaChange)
dat6.append(omim_list)
dat7.append(uni_list)
dat8.append(hgmd_list)
dat9.append(hbvar_list)
dat10.append(alist[3])
dat11.append(alist[4])
dat12.append(alist[5])
dat13.append(alist[6])
dat14.append(alist[7])
dat15.append(alist[8])
dat16.append(alist[9])
dat17.append(alist[10])
dat18.append(alist[11])
dat19.append(alist[12])
dat20.append(alist[13])
dat21.append(alist[14])
dat22.append(alist[15])
dat23.append(alist[16])
dat24.append(alist[17])
dat25.append(alist[18])
dat26.append(alist[19])
dat27.append(alist[20])
dat28.append(alist[21])
dat29.append(alist[22])
dat30.append(alist[23])
dat31.append(alist[24])
dat32.append(alist[25])
dat33.append(alist[26])
dat34.append(alist[27])
dat35.append(alist[28])
dat36.append(alist[29])
dat37.append(alist[30])
dat38.append(AF_ESP)
dat39.append(AF_EXAC)
dat40.append(AF_TGP)
# Creating DF from lists
df1 = []
df1 = pd.DataFrame(list(zip(dat1,dat2,dat3,dat4,dat5,dat6,dat7,dat8,dat9,dat10,dat11,dat12,dat13,dat14,dat15,dat16,dat17,dat18,dat19,dat20,dat21,dat22,dat23,dat24,dat25,dat26,dat27,dat28,dat29,dat30,dat31,dat32,dat33,dat34,dat35,dat36,dat37,dat38,dat39,dat40)), columns = ['alleleID','Type','Name','HGVSName','ProteinChange','OMIM','UniProt','HGMD','HBVAR','GeneID','GeneSymbol','HGNC_ID','ClinicalSignificance','ClinSigSimple','LastEvaluated',"RS# (dbSNP)",'nsv/esv (dbVar)','RCVaccession','PhenotypeIDS','PhenotypeList','Origin','OriginSimple','Assembly','ChromosomeAccession','Chromosome','Start','Stop','ReferenceAllele','AlternateAllele','Cytogenetic','ReviewStatus','NumberSubmitters','Guidelines','TestedInGTR','OtherIDs','SubmitterCategories','VariationID','AF_ESP','AF_EXAC','AF_TGP'])
解决方案
好吧,我终于能够加速这个程序,只需用 df.loc 替换 np.where 就可以将它从 19 小时缩短到 5 小时左右。这是替换的代码:
df.loc[df['alleleID'].isin([a1[0]]), 'info'].values
有许多方法可以实现 df.loc 搜索/过滤,但有趣或令人惊讶的是,在互联网上,所有这些方法都给出了作为字符串传递的值的示例(例如:像 '9879' 或 'hosting')。像这样的东西,我必须在 df 中搜索 15072。
df.loc[df['alleleID'] == '15072']
现在,这工作正常,但我的问题是我正在从另一个文件中读取值,所以我在变量中有值,所以我尝试如下:
var = 15072
df.loc[df['alleleID'] == var]
现在,这个不起作用并由于某种原因给出错误。
因此,我进行了更多探索并做了一些修改,并使用了一个只有一个值的列表。如下:
list_a = []
list_a = ['15072']
df.loc[df['alleleID'].isin([list_a[0]]), 'info'].values
这终于奏效了,从 19 小时到 5 小时有了很大的改善。
推荐阅读
- python - 计算/可视化 Tensorflow Keras Dense 模型层相对连接权重 wrt 输出类
- linux - 我无法克服的 yaml 烦人问题
- java - JFrame在打开时陷入了一些奇怪的内部死锁
- node.js - bash,nohup sh 文件启动节点并且节点在注销时挂起?
- javascript - 如何通过 textarea 的大小限制 textarea 中的字符?
- scala - 将 Akka Http 服务的一些路径参数更改为查询参数
- spring - 重定向在生产一段时间后停止工作
- javascript - 在另一个对象的构造函数中创建一个新的 ES6 对象失败
- c++ - C++ 环境变量
- unix - 如何将两个 Vim 命令合二为一(命令不是键绑定)