Этот вопрос, вероятно, лучше подходит для решения на основе графов. Ничто не препятствует перекрытию нескольких диапазонов с разными интервалами.
#!/usr/bin/env python3
from pprint import pprint
from itertools import groupby
def mapper(d, overlap=1000):
"""Each chromsomal coordinate must be interrogated
to determine if it is within +/-overlap of any other
Range within any other Original Dictionary Transcript
value will match key and chromosome element from the list
------------------------ ---------------------- ----------
(el-overlap, el+overlap), (dict-key, chromosome), el)
"""
for key, ch in d.items():
for el in ch[1:]:
yield ((el-overlap, el+overlap), (key, ch[0]), el)
def sorted_mapper(d, overlap=1000):
"""Simply sort the mapper data by its first element
"""
for r in sorted(mapper(d, overlap), key=lambda x: x[0]):
yield r
def groups(iter_):
previous = next(iter_)
retval = [previous]
for chrm in iter_:
if previous[0][0] <= chrm[-1] <= previous[0][1]:
retval.append(chrm)
else:
yield retval
previous = chrm
retval = [previous]
yield retval
def reduce_phase1(iter_):
for l in iter_:
retval = {}
for (minc, maxc), (key, lbl), chrm in l:
x = retval.get(key,[lbl])
x.append(chrm)
retval[key] = x
yield retval
def update_dict(d1, d2):
retval = d1
for key, value in d2.items():
if key in d1.keys():
retval[key].extend(value[1:])
return retval
def reduce_phase2(iter_):
retval = [next(iter_)]
retval_keys = [set([k for k in retval[0].keys()])]
for d in iter_:
keyset = set([k for k in d.keys()])
isnew = True
for i, e in enumerate(retval_keys):
if keyset <= e:
isnew = False
retval[i] = update_dict(retval[i], d)
if isnew:
retval.append(d)
retval_keys.append(keyset)
return retval
First_dict = {Key1: ['chr10', 19010495, 19014590, 19014064],
Key2: ['chr10', 19010495, 19014658],
Key3: ['chr10', 19010502, 19014641],
Key4: ['chr10', 37375766, 37377526],
Key5: ['chr10', 76310389, 76315990, 76312224, 76312963],
Key6: ['chr11', 14806147, 14814006]}
New_list = [
{
"Key1": ['chr10', 19010495, 19014590, 19014064],
"Key2": ['chr10', 19010495, 19014658],
"Key3": ['chr10', 19010502, 19014641]
},
{"Key4": ['chr10', 37375766, 37377526]},
{"Key5": ['chr10', 76310389, 76315990, 76312224, 76312963]},
{"Key6": ['chr11', 14806147, 14814006]}
]
pprint(First_dict)
print('-'*40)
g = groups(sorted_ranges(First_dict))
p1 = reduce_phase1(groups(sorted_ranges(First_dict)))
p2 = reduce_phase2(p1)
pprint(p2)
Выход
{'Key1': ['chr10', 19010495, 19014590, 19014064],
'Key2': ['chr10', 19010495, 19014658],
'Key3': ['chr10', 19010502, 19014641],
'Key4': ['chr10', 37375766, 37377526],
'Key5': ['chr10', 76310389, 76315990, 76312224, 76312963],
'Key6': ['chr11', 14806147, 14814006]}
----------------------------------------
[{'Key6': ['chr11', 14806147, 14814006]},
{'Key1': ['chr10', 19010495, 19014064, 19014590],
'Key2': ['chr10', 19010495, 19014658],
'Key3': ['chr10', 19010502, 19014641]},
{'Key4': ['chr10', 37375766, 37377526]},
{'Key5': ['chr10', 76310389, 76312224, 76312963, 76315990]}]
TLDR;
Выход Mapper
Отображатель испускает запись для каждого ключа словаря и хромосомного элемента. Каждая запись имеет соответствующий диапазон, в котором ее элемент может быть сопоставлен.
((el-1000, el+1000), (dict-key, chromosome), el)
(el-1000, el + 1000) - это диапазон, в котором может совпадать любой другой хромосомный элемент.
(dict-key, chromosome) исходный словарь для этой хромосомы.
el является одним элементом из хромосомной координаты.
((19009495, 19011495), ('Key1', 'chr10'), 19010495)
((19013590, 19015590), ('Key1', 'chr10'), 19014590)
((19013064, 19015064), ('Key1', 'chr10'), 19014064)
((19009495, 19011495), ('Key2', 'chr10'), 19010495)
((19013658, 19015658), ('Key2', 'chr10'), 19014658)
((19009502, 19011502), ('Key3', 'chr10'), 19010502)
((19013641, 19015641), ('Key3', 'chr10'), 19014641)
((37374766, 37376766), ('Key4', 'chr10'), 37375766)
((37376526, 37378526), ('Key4', 'chr10'), 37377526)
((76309389, 76311389), ('Key5', 'chr10'), 76310389)
((76314990, 76316990), ('Key5', 'chr10'), 76315990)
((76311224, 76313224), ('Key5', 'chr10'), 76312224)
((76311963, 76313963), ('Key5', 'chr10'), 76312963)
((14805147, 14807147), ('Key6', 'chr11'), 14806147)
((14813006, 14815006), ('Key6', 'chr11'), 14814006)
ПРИМЕЧАНИЕ: Выход из преобразователя не отсортирован.
Сортировка
Нам нужно отсортировать преобразованные данные, используя (el-1000, el + 1000) в качестве ключа.
Это позволит нам проверить, находится ли следующее значение в пределах диапазона предыдущего значения. Поскольку ключи расположены в отсортированном порядке, мы сможем объединить значения, которые находятся в пределах указанного перекрытия.
((14805147, 14807147), ('Key6', 'chr11'), 14806147)
((14813006, 14815006), ('Key6', 'chr11'), 14814006)
((19009495, 19011495), ('Key1', 'chr10'), 19010495)
((19009495, 19011495), ('Key2', 'chr10'), 19010495)
((19009502, 19011502), ('Key3', 'chr10'), 19010502)
((19013064, 19015064), ('Key1', 'chr10'), 19014064)
((19013590, 19015590), ('Key1', 'chr10'), 19014590)
((19013641, 19015641), ('Key3', 'chr10'), 19014641)
((19013658, 19015658), ('Key2', 'chr10'), 19014658)
((37374766, 37376766), ('Key4', 'chr10'), 37375766)
((37376526, 37378526), ('Key4', 'chr10'), 37377526)
((76309389, 76311389), ('Key5', 'chr10'), 76310389)
((76311224, 76313224), ('Key5', 'chr10'), 76312224)
((76311963, 76313963), ('Key5', 'chr10'), 76312963)
((76314990, 76316990), ('Key5', 'chr10'), 76315990)
Группировать
Группировать значения, которые находятся в пределах указанного перекрытия. Появляющиеся списки будут содержать значения из хромосом, которые находятся в перекрытии предыдущей хромосомы.
[((14805147, 14807147), ('Key6', 'chr11'), 14806147)]
----------------------------------------
[((14813006, 14815006), ('Key6', 'chr11'), 14814006)]
----------------------------------------
[((19009495, 19011495), ('Key1', 'chr10'), 19010495),
((19009495, 19011495), ('Key2', 'chr10'), 19010495),
((19009502, 19011502), ('Key3', 'chr10'), 19010502)]
----------------------------------------
[((19013064, 19015064), ('Key1', 'chr10'), 19014064),
((19013590, 19015590), ('Key1', 'chr10'), 19014590),
((19013641, 19015641), ('Key3', 'chr10'), 19014641),
((19013658, 19015658), ('Key2', 'chr10'), 19014658)]
----------------------------------------
[((37374766, 37376766), ('Key4', 'chr10'), 37375766)]
----------------------------------------
[((37376526, 37378526), ('Key4', 'chr10'), 37377526)]
----------------------------------------
[((76309389, 76311389), ('Key5', 'chr10'), 76310389)]
----------------------------------------
[((76311224, 76313224), ('Key5', 'chr10'), 76312224),
((76311963, 76313963), ('Key5', 'chr10'), 76312963)]
----------------------------------------
[((76314990, 76316990), ('Key5', 'chr10'), 76315990)]
----------------------------------------
Уменьшение - Фаза 1
Очистить данные, удалив встроенные функции.
{'Key6': ['chr11', 14806147]}
----------------------------------------
{'Key6': ['chr11', 14814006]}
----------------------------------------
{'Key1': ['chr10', 19010495],
'Key2': ['chr10', 19010495],
'Key3': ['chr10', 19010502]}
----------------------------------------
{'Key1': ['chr10', 19014064, 19014590],
'Key2': ['chr10', 19014658],
'Key3': ['chr10', 19014641]}
----------------------------------------
{'Key4': ['chr10', 37375766]}
----------------------------------------
{'Key4': ['chr10', 37377526]}
----------------------------------------
{'Key5': ['chr10', 76310389]}
----------------------------------------
{'Key5': ['chr10', 76312224, 76312963]}
----------------------------------------
{'Key5': ['chr10', 76315990]}
----------------------------------------
Reduce - Phase 2
Объедините смещенные ключи словаря с их исходным словарем. Добавьте значения для соответствующей хромосомы, когда ключи словаря совпадают.
{'Key6': ['chr11', 14806147, 14814006]}
----------------------------------------
{'Key1': ['chr10', 19010495, 19014064, 19014590],
'Key2': ['chr10', 19010495, 19014658],
'Key3': ['chr10', 19010502, 19014641]}
----------------------------------------
{'Key4': ['chr10', 37375766, 37377526]}
----------------------------------------
{'Key5': ['chr10', 76310389, 76312224, 76312963, 76315990]}
----------------------------------------