如何在Pandas脚本上利用矢量化以提高效率?

时间:2018-10-26 09:51:01

标签: python pandas performance vectorization

这是我先前的post的延续,在那儿,我想要一个更快,更高效的替代标准Python循环的方法,该循环对每行的元素执行一些求和和乘法。

基本上,我有两个文件输入。一个是一组SNP的所有组合的列表,例如下面的3个SNP:

    AA   CC   TT
    AT   CC   TT
    TT   CC   TT
    AA   CG   TT
    AT   CG   TT
    TT   CG   TT
    AA   GG   TT
    AT   GG   TT
    TT   GG   TT
    AA   CC   TA
    AT   CC   TA
    TT   CC   TA
    AA   CG   TA
    AT   CG   TA
    TT   CG   TA
    AA   GG   TA
    AT   GG   TA
    TT   GG   TA
    AA   CC   AA
    AT   CC   AA
    TT   CC   AA
    AA   CG   AA
    AT   CG   AA
    TT   CG   AA
    AA   GG   AA
    AT   GG   AA
    TT   GG   AA

第二个是表格,其中包含每个SNP的一些信息,尤其是疾病的log(OR)和风险等位基因的频率:

SNP1             A       T       1.25    0.223143551314     0.97273 
SNP2             C       G       1.07    0.0676586484738    0.3     
SNP3             T       A       1.08    0.0769610411361    0.1136  

下面是我的主要代码,其中我希望为每个“配置文件”计算一个“得分”和一个“频率”。得分是配置文件中每个风险等位基因的log(OR)的总和,而频率是假设Hardy Weinberg平衡的频率相乘的结果:

import pandas as pd

numbers = pd.read_csv(table2, sep="\t", header=None)

combinations = pd.read_csv(table1, sep=" ", header=None)

def score_freq(line):
    score=0
    freq=1
    for j in range(len(line)):
        if line[j][1] != numbers.values[j][1]:   # homozygous for ref
            score+=0
            freq*=(float(1-float(numbers.values[j][6]))*float(1-float(numbers.values[j][6])))
        elif line[j][0] != numbers.values[j][1] and line[j][1] == numbers.values[j][1]: # heterozygous
            score+=(float(numbers.values[j][5]))
            freq*=(2*(float(1-float(numbers.values[j][6]))*float(numbers.values[j][6])))
        elif line[j][0] == numbers.values[j][1]:   # homozygous for risk
            score+=2*(float(numbers.values[j][5]))
            freq*=(float(numbers.values[j][6])*float(numbers.values[j][6]))

        if freq < 1e-05:   # threshold to stop loop in interest of efficiency 
            break

    return pd.Series([score, freq])

combinations[['score', 'freq']] = combinations.apply(lambda row: score_freq(row), axis=1)
#combinations[['score', 'freq']] = score_freq(combinations.values) # vectorization?

print(combinations)

我指的是this site,在这里他们讨论了循环遍历Pandas数据帧的最快方法。我已经可以使用Pandas套用方法,但是我不确定如何在Pandas系列上执行矢量化方法。除此之外,请提出任何可以改善脚本以使其更高效的方法,谢谢!

1 个答案:

答案 0 :(得分:0)

我建议利用NumPy Python库使您的pd脚本更高效。 NumPy背后的想法是,您可以使用向量化来避免FOR循环,因此可以非常有效地处理数据负载。使用Numpy时,基本上是将数据转换为Numpy数组。您可以找到详细的文档here。要回答您的问题,您可以像这样对numpy数组执行数学运算:

a = np.array([1, 2, 3, 4])
a + 1                // to add 1 to every element in the array

a * 2                // to multiply each element in the array by 2

这比在纯python中的FOR循环中使用效率更高。

希望这会有所帮助。