Dav*_*ell 5 python bioinformatics biopython pandas
我是一名新近自学成才的(减去 1 节非常基础的课程)程序员,在生物实验室工作。我有一个脚本,它遍历来自两种不同细胞类型的 RNAseq 数据,并在另一个数据集中运行 ttest。它适用于这个应用程序,但代码感觉非常粗鲁,我知道我会写很多类似的脚本。
如何更好地编写以下代码以使其更高效?
计划目标:
:
import pandas as pd
from scipy.stats import ttest_ind
rnatest = {'Gene symbol':["GeneA","GeneB"],"rnaseq1A":[1,1.5],"rnaseq1B":[1.3,1.2],"rnaseq2A":[2.3,2.7],"rnaseq2B":[2,2.6]}
df = pd.DataFrame(rnatest)
GOIlist = ["GeneA","GeneB"]
GOI = []
mu = []
pval = []
for index, row in df.iterrows():
if row['Gene symbol'] in GOIlist:
t, p = ttest_ind([row["rnaseq1A"],row["rnaseq1B"]],[row["rnaseq2A"],row["rnaseq2B"]])
GOI.append(row['Gene symbol'])
mu.append(t)
pval.append(p)
df2 = {'Gene symbol':GOI,"tVAL":mu, "pVAL":pval}
df2 = pd.DataFrame(df2)
print(df2)
Run Code Online (Sandbox Code Playgroud)
使用的好处pandas是可以进行列操作。这些通常比使用 for 循环迭代 DataFrame 更有效。
我稍微修改了您df以向您展示过滤掉我们需要的行的效果。
>>> import pandas as pd
>>> from scipy.stats import ttest_ind
>>> GOIlist = ["GeneA","GeneB"]
>>> rnatest = {'Gene symbol':["GeneA","GeneB", "GeneC"],"rnaseq1A":[1,1.5,2],"rnaseq1B":[1.3,1.2,1.1],"rnaseq2A":[2.3,2.7,3.1],"rnaseq2B":[2,2.6,3.2]}
>>> df = pd.DataFrame(rnatest)
>>> print(df)
Gene symbol rnaseq1A rnaseq1B rnaseq2A rnaseq2B
0 GeneA 1.0 1.3 2.3 2.0
1 GeneB 1.5 1.2 2.7 2.6
2 GeneC 2.0 1.1 3.1 3.2
Run Code Online (Sandbox Code Playgroud)
现在我将如何重写您的代码:
set_index使Gene symbol排索引,这加快了查找时间(特别是如果你有大量DataFrames)loc筛选出具有基因符号是在行GOIlistpVal,并tVal到您指定的输出ttest_ind。请注意,我们不必再遍历行了。rnaseq*如果您不想在输出中看到它们,请删除这些列。在代码中:
>>> df3 = df.set_index(['Gene symbol'])
>>> df3 = df3.loc[GOIlist]
>>> df3['tVal'], df3['pVal'] = ttest_ind([df3["rnaseq1A"], df3["rnaseq1B"]], [df3["rnaseq2A"], df3["rnaseq2B"]])
>>> df3 = df3.drop(['rnaseq1A', 'rnaseq1B', 'rnaseq2A', 'rnaseq2B'], axis=1)
>>> print(df3)
tVal pVal
Gene symbol
GeneA -4.714045 0.042174
GeneB -8.221922 0.014473
Run Code Online (Sandbox Code Playgroud)
那么,现在这段代码的效率有多高呢?
如果我人为地将 DataFrame 的大小增加 10.000 倍(因此总共有 30.000 行而不是 3 行)
n = 10_000
rnatest = {'Gene symbol':["GeneA","GeneB", "GeneC"]*n, "rnaseq1A":[1,1.5,2]*n, "rnaseq1B":[1.3,1.2,1.1]*n, "rnaseq2A":[2.3,2.7,3.1]*n, "rnaseq2B":[2,2.6,3.2]*n}
df = pd.DataFrame(rnatest)
Run Code Online (Sandbox Code Playgroud)
然后我可以用它timeit来衡量代码的执行时间。对于您的原始方法,我得到了结果:
13.7 s ± 555 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Run Code Online (Sandbox Code Playgroud)
当我的方法结束时
45.2 ms ± 1.27 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Run Code Online (Sandbox Code Playgroud)
所以这是一个超过 300 倍的加速!