嵌套循环输出到 dict 并行

Nested loops output to dict in parallel

我有两组数据:

aDict = {'barcode1': [('barcode1', 184), ('barcode1_mut', 2)], 'barcode2': [('barcode2', 138)], 'barcode3': [('barcode3', 375)]}
bList = [(('barcode1', 'mut1'), 184), (('barcode1_mut', 'mut2'), 2), (('barcode2', 'mut3'), 136), (('barcode2', 'mut4'), 1), (('barcode2', 'mut5'), 1), (('barcode3', 'mut6'), 373), (('barcode3', 'mut7'), 2)]

我正在用列表 bList 和结果中的条形码匹配字典 aDict 中的每个键和结果:

>>>print(result)
{'barcode1': {'barcode1': [('mut1', 184)], 'barcode1_mut': [('mut2', 2)]},
'barcode2': {'barcode2': [('mut3', 136), ('mut4', 1), ('mut5', 1)]},
'barcode3': {'barcode3': [('mut6', 373), ('mut7', 2)]}}

但对我来说太慢了。我尝试将代码与处理行数的信息输出并行。但是在我的实现中,每一行都是由所有工人同时处理的。

现在,我的实现看起来像:

from collections import defaultdict
import multiprocessing as mp

def f(uniqueBarcode):
    mutBarcodeList = [x[0] for x in aDict[uniqueBarcode]]
    a = filter(lambda x: x[0][0] in mutBarcodeList, bList.items())
    d = defaultdict(tuple)
    b = [(x[0][0], (x[0][1], x[1])) for x in a]
    for tup in b: d[tup[0]] += (tup[1],)
    result = {i[0]:[y for y in i[1]] for i in d.items()}
    return result

seqDict={}

if __name__=='__main__':
    cpus = mp.cpu_count()
    pool = mp.Pool(cpus)
    for barcode in aDict.keys():
        seqDict[barcode] = pool.map(f, [barcode])
        if len(seqDict) % 100 == 0:
            print("Processed {} barcodes".format(len(seqDict)))
    pool.close()
    pool.join()

输出:

Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 100 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
Processed 200 barcodes
...

而dict seqDict是空的,但一定不是这样——第一行是第一个进程处理的,第二行是第二个...第八个是第八个过程,第九行又是第一个过程等等

如何正确地并联?

Upd0: 我把 Flomp 的代码改成了我自己

res={}
for key in aDict:
    if len(aDict[key]) == 1:
        res[key] = {key:[(a[1],b) for a,b in bList if a[0] == key]}
    elif len(aDict[key]) > 1:
        res[key] = {x[0]:[(a[1],b) for a,b in bList if a[0] == x[0]] for x in aDict[key]}

但它工作了这么久

我在您的代码中看到了很多 for 循环。这会减慢你的程序。这是一些 运行time 更好的代码:

bcDict = {'TTCTCTTACCGGGTAC':1,'ACCTCTCGAGAATTCA':2,'TGCAGTTCTGTGCATC':3}

bcMutCount = [(('TTCTCTTACCGGGTAC', 'ATTCAACA'), 184), 
(('ACCTCTCGAGAATTCA', 'CATCCCAC'), 136), 
(('ACCTCTCGAGAATTCA', 'CATGCCAC'), 1),
(('ACCTCTCGAGAATTCA', 'CATCCCCC'), 1),
(('TGCAGTTCTGTGCATC', 'TCTACATT'), 373),
(('TGCAGTTCTGTGCATC', 'ACTGCGCA'), 2)]


for key in bcDict:
  print({key:[(a[1],b) for a,b in bcMutCount if a[0] == key]})

输出:

{'TTCTCTTACCGGGTAC': [('ATTCAACA', 184)]}
{'ACCTCTCGAGAATTCA': [('CATCCCAC', 136), ('CATGCCAC', 1), ('CATCCCCC', 1)]}
{'TGCAGTTCTGTGCATC': [('TCTACATT', 373), ('ACTGCGCA', 2)]}

如果这不是您想要的,请纠正我。上面的代码应该 运行 in O(m*n) 其中 m 是 bcDict 中的键数, n 是 bcMutCount 的长度。 这个运行够快吗?

首先:将bList转成dict

bDict = {
('barcode1', 'mut1'): 184, 
('barcode1_mut', 'mut2'): 2, 
('barcode2', 'mut3'): 136, 
('barcode2', 'mut4'): 1, 
('barcode2', 'mut5'): 1, 
('barcode3', 'mut6'): 373, 
('barcode3', 'mut7'): 2}

第二:将值与相同的条形码合并。

mDict = {}
for x, y in bDict.items():
    if mDict.get(x[0]) == None:
        mDict[x[0]] = [(x[1], y)]
    else:
        mDict[x[0]].append((x[1], y))
>>>print(mDict)
{'barcode1': [('mut1', 184)],
'barcode1_mut': [('mut2', 2)],
'barcode2': [('mut3', 136), ('mut4', 1), ('mut5', 1)],
'barcode3': [('mut6', 373), ('mut7', 2)]}

第三:将结果分配给唯一的条形码。

seqDict = {x: {y[0]: mDict[y[0]] for y in aDict[x]} for x in aDict.keys()}