首先,对不起,如果这有点长,但我想完整地描述我遇到的问题以及我已经尝试过的事情。
我试图在多个条件下将两个数据框对象连接(合并)在一起。如果要满足的条件都是等于'等等,我知道如何做到这一点。然而,运营商,我需要使用的不仅仅是比这更多。
数据框表示遗传信息:一个是基因组中的突变列表(称为SNP),另一个是基因在人类基因组上的位置信息。对它们执行df.head()将返回以下内容:
chromosome SNP BP
0 1 rs3094315 752566
1 1 rs3131972 752721
2 1 rs2073814 753474
3 1 rs3115859 754503
4 1 rs3131956 758144
显示SNP参考ID及其位置。 ' BP'代表' Base-Pair'位置。
chromosome chr_start chr_stop feature_id
0 1 10954 11507 GeneID:100506145
1 1 12190 13639 GeneID:100652771
2 1 14362 29370 GeneID:653635
3 1 30366 30503 GeneID:100302278
4 1 34611 36081 GeneID:645520
该数据框显示了所有感兴趣的基因的位置。
我想知道的是所有属于基因组中基因区域的SNP,并丢弃那些位于这些区域之外的SNP。
如果我想基于多个(等于)条件将两个数据帧合并在一起,我会做类似以下的事情:
merged_df = pd.merge(snp_df, gene_df, on=['chromosome', 'other_columns'])
然而,在这种情况下 - 我需要找到染色体值与基因数据帧中的那些匹配的SNP,并且BP值落在< chr_start'之间。和' chr_stop'。这种挑战的原因是这些数据帧非常大。在当前数据集中,snp_df有6795021行,而gene_df有34362。
我试图通过分别观察染色体或基因来解决这个问题。由于未使用性染色体,因此有22种不同的染色体值(第1-22位)。这两种方法都耗费了很长时间。一个使用pandasql
模块,而另一个方法是循环使用不同的基因。
import pandas as pd
import pandasql as psql
pysqldf = lambda q: psql.sqldf(q, globals())
q = """
SELECT s.SNP, g.feature_id
FROM this_snp s INNER JOIN this_genes g
WHERE s.BP >= g.chr_start
AND s.BP <= g.chr_stop;
"""
all_dfs = []
for chromosome in snp_df['chromosome'].unique():
this_snp = snp_df.loc[snp_df['chromosome'] == chromosome]
this_genes = gene_df.loc[gene_df['chromosome'] == chromosome]
genic_snps = pysqldf(q)
all_dfs.append(genic_snps)
all_genic_snps = pd.concat(all_dfs)
all_dfs = []
for line in gene_df.iterrows():
info = line[1] # Getting the Series object
this_snp = snp_df.loc[(snp_df['chromosome'] == info['chromosome']) &
(snp_df['BP'] >= info['chr_start']) & (snp_df['BP'] <= info['chr_stop'])]
if this_snp.shape[0] != 0:
this_snp = this_snp[['SNP']]
this_snp.insert(len(this_snp.columns), 'feature_id', info['feature_id'])
all_dfs.append(this_snp)
all_genic_snps = pd.concat(all_dfs)
任何人都可以提出更有效的方法吗?
答案 0 :(得分:2)
我只想到一种解决方法 - 通过结合我的两种方法:
首先,关注单个染色体,然后在这些较小的数据帧中循环基因。这也不必使用任何SQL查询。我还包括一个部分,可以立即识别出任何不具备任何SNP的冗余基因。这使用了我通常试图避免的双循环 - 但在这种情况下它运行得很好。
all_dfs = []
for chromosome in snp_df['chromosome'].unique():
this_chr_snp = snp_df.loc[snp_df['chromosome'] == chromosome]
this_genes = gene_df.loc[gene_df['chromosome'] == chromosome]
# Getting rid of redundant genes
min_bp = this_chr_snp['BP'].min()
max_bp = this_chr_snp['BP'].max()
this_genes = this_genes.loc[~(this_genes['chr_start'] >= max_bp) &
~(this_genes['chr_stop'] <= min_bp)]
for line in this_genes.iterrows():
info = line[1]
this_snp = this_chr_snp.loc[(this_chr_snp['BP'] >= info['chr_start']) &
(this_chr_snp['BP'] <= info['chr_stop'])]
if this_snp.shape[0] != 0:
this_snp = this_snp[['SNP']]
this_snp.insert(1, 'feature_id', info['feature_id'])
all_dfs.append(this_snp)
all_genic_snps = pd.concat(all_dfs)
虽然这并没有很快地运行 - 它确实运行,所以我实际上可以得到一些答案。我还是想知道是否有人有任何提示让它更有效率地运行。
答案 1 :(得分:1)
您可以使用以下内容来完成您正在寻找的内容:
merged_df=snp_df.merge(gene_df,on=['chromosome'],how='inner')
merged_df=merged_df[(merged_df.BP>=merged_df.chr_start) & (merged_df.BP<=merged_df.chr_stop)][['SNP','feature_id']]
注意:您的示例数据框不符合您的加入条件。以下是使用修改后的数据框的示例:
snp_df
Out[193]:
chromosome SNP BP
0 1 rs3094315 752566
1 1 rs3131972 30400
2 1 rs2073814 753474
3 1 rs3115859 754503
4 1 rs3131956 758144
gene_df
Out[194]:
chromosome chr_start chr_stop feature_id
0 1 10954 11507 GeneID:100506145
1 1 12190 13639 GeneID:100652771
2 1 14362 29370 GeneID:653635
3 1 30366 30503 GeneID:100302278
4 1 34611 36081 GeneID:645520
merged_df
Out[195]:
SNP feature_id
8 rs3131972 GeneID:100302278