使用一个衬里而不是 for 循环对 Python 中的字典中的字典中的选定元素求和
Sum selected elements in dict of dicts in Python using one liner instead of for-loop
我使用了下面的字典理解
dimer = {(ab+cd):{"1":0,"2":0,"3":0} for cd in 'ACGT' for ab in 'ACGT'}
生成一个dict of dicts,dimer:
dimer = {"AA":{"1":0,"2":0,"3":0}, "AC":{"1":0,"2":0,"3":0}, "AG":{"1":0,"2":0,"3":0}, "AT":{"1":0,"2":0,"3":0}, "CA":{"1":0,"2":0,"3":0}, "CC":{"1":0,"2":0,"3":0}, "CG":{"1":0,"2":0,"3":0}, "CT":{"1":0,"2":0,"3":0}, "GA":{"1":0,"2":0,"3":0}, "GC":{"1":0,"2":0,"3":0}, "GG":{"1":0,"2":0,"3":0}, "GT":{"1":0,"2":0,"3":0}, "TA":{"1":0,"2":0,"3":0}, "TC":{"1":0,"2":0,"3":0}, "TT":{"1":0,"2":0,"3":0}, "TG":{"1":0,"2":0,"3":0}}
不过,现在我想对所选元素进行总结,
如果我将它们硬编码出来,就像
total_A = dimer["AA"]["1"]+dimer["CA"]["1"]+dimer["GA"]["1"]+dimer["TA"]["1"]+dimer["AA"]["2"]+dimer["CA"]["2"]+dimer["GA"]["2"]+dimer["TA"]["2"]+dimer["AA"]["3"]+dimer["CA"]["3"]+dimer["GA"]["3"]+dimer["TA"]["3"]
total_C = dimer["AC"]["1"]+dimer["CC"]["1"]+dimer["GC"]["1"]+dimer["TC"]["1"]+dimer["AC"]["2"]+dimer["CC"]["2"]+dimer["GC"]["2"]+dimer["TC"]["2"]+dimer["AC"]["3"]+dimer["CC"]["3"]+dimer["GC"]["3"]+dimer["TC"]["3"]
total_G = dimer["AG"]["1"]+dimer["CG"]["1"]+dimer["GG"]["1"]+dimer["TG"]["1"]+dimer["AG"]["2"]+dimer["CG"]["2"]+dimer["GG"]["2"]+dimer["TG"]["2"]+dimer["AG"]["3"]+dimer["CG"]["3"]+dimer["GG"]["3"]+dimer["TG"]["3"]
total_T = dimer["AT"]["1"]+dimer["CT"]["1"]+dimer["GT"]["1"]+dimer["TT"]["1"]+dimer["AT"]["2"]+dimer["CT"]["2"]+dimer["GT"]["2"]+dimer["TT"]["2"]+dimer["AT"]["3"]+dimer["CT"]["3"]+dimer["GT"]["3"]+dimer["TT"]["3"]
我想出的最好的简化方法是使用嵌套的 for 循环:
total_0 = {i:0 for i in 'ACGT'}
for i in 'ACGT':
for j in 'ACGT':
for k in '123':
total_0[i] += dimer[j+i][k]
我想知道有没有什么方法可以用一根线来总结它们?
我还有另一个嵌套的 for 循环:
row_sum = {i:{"1":0,"2":0,"3":0} for i in 'ACGT'}
for i in 'ACGT':
for j in 'ACGT':
for k in '123':
row_sum[i][k] += float(dimer[i+j][k])
硬编码版本如下:
row_sum = {"A":{"1":0,"2":0,"3":0},"C":{"1":0,"2":0,"3":0},"G":{"G":0,"2":0,"3":0},"T":{"1":0,"2":0,"3":0}}
for i in range(1,4,1):
row_sum["A"][str(i)] = float(dimer["AA"][str(i)]+dimer["AC"][str(i)]+dimer["AG"][str(i)]+dimer["AT"][str(i)])
row_sum["C"][str(i)] = float(dimer["CA"][str(i)]+dimer["CC"][str(i)]+dimer["CG"][str(i)]+dimer["CT"][str(i)])
row_sum["G"][str(i)] = float(dimer["GA"][str(i)]+dimer["GC"][str(i)]+dimer["GG"][str(i)]+dimer["GT"][str(i)])
row_sum["T"][str(i)] = float(dimer["TA"][str(i)]+dimer["TC"][str(i)]+dimer["TG"][str(i)]+dimer["TT"][str(i)])
我也想知道是否有任何方法可以使用一个衬里来总结第二个嵌套的for循环?
抱歉,我是 Python 的新手。任何帮助将不胜感激!
首先,您可以使用像这样的笛卡尔积将 3 个循环合并为一个循环。
from itertool import product
row_sum = {i: {"1": 0, "2": 0, "3": 0} for i in NT}
for i, j, k in product('ACGT', 'ACGT', '123'):
row_sum[i][k] += float(dimer[i + j][k])
这是单行本,但如果您是 Python
的新手,可能很难理解
{i: sum(sum(dimer[i + j].values()) for j in 'ACGT') for i in 'ACGT'}
我不知道这将如何与您的程序的其余部分相结合,但可能值得切换到不同的数据结构。如果您将二聚体集合表示为单个 numpy
整数数组,您将拥有单行代码,并且还会看到大幅加速。例如,您的二聚体可以这样表示:
import numpy as np
dimer = np.zeros((4,4,3),dtype=int)
这里第一个索引中的0,1,2,3表示二聚体中的第一个元素是否为A,C,G,T,第二个索引同理,而第三个索引包含三种不同的情况您标记为“1”、“2”或“3”。所以你的 dimer["AG"]["1"]
在这里会是 dimer[0,2,0]
(因为 numpy 从零开始计数)。
使用这样的结构的好处是
- 如果您的数据集变大(例如,如果每个二聚体有 300000 个元素而不是 3 个元素),它会更快并且内存效率更高。
- 有很多函数可用于操作
numpy
数组。例如,np.sum(dimer,2)
会给出每个二聚体的元素总数。
您想要的汇总统计数据可以计算为:
total_0 = np.sum(dimer, (0,2))
row_sum = np.sum(dimer, 1)
作为速度差异的说明,对于您的问题大小,使用 for 循环的 dict
方法需要 20 微秒来计算 total_0
,而 numpy
总和需要 5.7微秒。对于一个大 1000 倍的问题,其中每个二聚体有 3000 个成员,dict
方法需要 22 毫秒,而 numpy
需要 31 微秒。对于一个大 1,000,000 倍的问题,dict
需要 24.5 秒,而 numpy
需要 24.3 毫秒。所以对于大问题,numpy
比使用字典快 1000 倍。
我使用了下面的字典理解
dimer = {(ab+cd):{"1":0,"2":0,"3":0} for cd in 'ACGT' for ab in 'ACGT'}
生成一个dict of dicts,dimer:
dimer = {"AA":{"1":0,"2":0,"3":0}, "AC":{"1":0,"2":0,"3":0}, "AG":{"1":0,"2":0,"3":0}, "AT":{"1":0,"2":0,"3":0}, "CA":{"1":0,"2":0,"3":0}, "CC":{"1":0,"2":0,"3":0}, "CG":{"1":0,"2":0,"3":0}, "CT":{"1":0,"2":0,"3":0}, "GA":{"1":0,"2":0,"3":0}, "GC":{"1":0,"2":0,"3":0}, "GG":{"1":0,"2":0,"3":0}, "GT":{"1":0,"2":0,"3":0}, "TA":{"1":0,"2":0,"3":0}, "TC":{"1":0,"2":0,"3":0}, "TT":{"1":0,"2":0,"3":0}, "TG":{"1":0,"2":0,"3":0}}
不过,现在我想对所选元素进行总结,
如果我将它们硬编码出来,就像
total_A = dimer["AA"]["1"]+dimer["CA"]["1"]+dimer["GA"]["1"]+dimer["TA"]["1"]+dimer["AA"]["2"]+dimer["CA"]["2"]+dimer["GA"]["2"]+dimer["TA"]["2"]+dimer["AA"]["3"]+dimer["CA"]["3"]+dimer["GA"]["3"]+dimer["TA"]["3"]
total_C = dimer["AC"]["1"]+dimer["CC"]["1"]+dimer["GC"]["1"]+dimer["TC"]["1"]+dimer["AC"]["2"]+dimer["CC"]["2"]+dimer["GC"]["2"]+dimer["TC"]["2"]+dimer["AC"]["3"]+dimer["CC"]["3"]+dimer["GC"]["3"]+dimer["TC"]["3"]
total_G = dimer["AG"]["1"]+dimer["CG"]["1"]+dimer["GG"]["1"]+dimer["TG"]["1"]+dimer["AG"]["2"]+dimer["CG"]["2"]+dimer["GG"]["2"]+dimer["TG"]["2"]+dimer["AG"]["3"]+dimer["CG"]["3"]+dimer["GG"]["3"]+dimer["TG"]["3"]
total_T = dimer["AT"]["1"]+dimer["CT"]["1"]+dimer["GT"]["1"]+dimer["TT"]["1"]+dimer["AT"]["2"]+dimer["CT"]["2"]+dimer["GT"]["2"]+dimer["TT"]["2"]+dimer["AT"]["3"]+dimer["CT"]["3"]+dimer["GT"]["3"]+dimer["TT"]["3"]
我想出的最好的简化方法是使用嵌套的 for 循环:
total_0 = {i:0 for i in 'ACGT'}
for i in 'ACGT':
for j in 'ACGT':
for k in '123':
total_0[i] += dimer[j+i][k]
我想知道有没有什么方法可以用一根线来总结它们?
我还有另一个嵌套的 for 循环:
row_sum = {i:{"1":0,"2":0,"3":0} for i in 'ACGT'}
for i in 'ACGT':
for j in 'ACGT':
for k in '123':
row_sum[i][k] += float(dimer[i+j][k])
硬编码版本如下:
row_sum = {"A":{"1":0,"2":0,"3":0},"C":{"1":0,"2":0,"3":0},"G":{"G":0,"2":0,"3":0},"T":{"1":0,"2":0,"3":0}}
for i in range(1,4,1):
row_sum["A"][str(i)] = float(dimer["AA"][str(i)]+dimer["AC"][str(i)]+dimer["AG"][str(i)]+dimer["AT"][str(i)])
row_sum["C"][str(i)] = float(dimer["CA"][str(i)]+dimer["CC"][str(i)]+dimer["CG"][str(i)]+dimer["CT"][str(i)])
row_sum["G"][str(i)] = float(dimer["GA"][str(i)]+dimer["GC"][str(i)]+dimer["GG"][str(i)]+dimer["GT"][str(i)])
row_sum["T"][str(i)] = float(dimer["TA"][str(i)]+dimer["TC"][str(i)]+dimer["TG"][str(i)]+dimer["TT"][str(i)])
我也想知道是否有任何方法可以使用一个衬里来总结第二个嵌套的for循环?
抱歉,我是 Python 的新手。任何帮助将不胜感激!
首先,您可以使用像这样的笛卡尔积将 3 个循环合并为一个循环。
from itertool import product
row_sum = {i: {"1": 0, "2": 0, "3": 0} for i in NT}
for i, j, k in product('ACGT', 'ACGT', '123'):
row_sum[i][k] += float(dimer[i + j][k])
这是单行本,但如果您是 Python
的新手,可能很难理解{i: sum(sum(dimer[i + j].values()) for j in 'ACGT') for i in 'ACGT'}
我不知道这将如何与您的程序的其余部分相结合,但可能值得切换到不同的数据结构。如果您将二聚体集合表示为单个 numpy
整数数组,您将拥有单行代码,并且还会看到大幅加速。例如,您的二聚体可以这样表示:
import numpy as np
dimer = np.zeros((4,4,3),dtype=int)
这里第一个索引中的0,1,2,3表示二聚体中的第一个元素是否为A,C,G,T,第二个索引同理,而第三个索引包含三种不同的情况您标记为“1”、“2”或“3”。所以你的 dimer["AG"]["1"]
在这里会是 dimer[0,2,0]
(因为 numpy 从零开始计数)。
使用这样的结构的好处是
- 如果您的数据集变大(例如,如果每个二聚体有 300000 个元素而不是 3 个元素),它会更快并且内存效率更高。
- 有很多函数可用于操作
numpy
数组。例如,np.sum(dimer,2)
会给出每个二聚体的元素总数。
您想要的汇总统计数据可以计算为:
total_0 = np.sum(dimer, (0,2))
row_sum = np.sum(dimer, 1)
作为速度差异的说明,对于您的问题大小,使用 for 循环的 dict
方法需要 20 微秒来计算 total_0
,而 numpy
总和需要 5.7微秒。对于一个大 1000 倍的问题,其中每个二聚体有 3000 个成员,dict
方法需要 22 毫秒,而 numpy
需要 31 微秒。对于一个大 1,000,000 倍的问题,dict
需要 24.5 秒,而 numpy
需要 24.3 毫秒。所以对于大问题,numpy
比使用字典快 1000 倍。