Как разобрать словарь, представляющий дендрограмму, чтобы создать другой словарь, представляющий все родительские и дочерние узлы?

Я работаю с данными RNA-seq мыши Allen Brain и из файла dend.json при условии, что я хочу создать словарь, в котором ключ является родительским узлом, а значением будет узлы, на которые родительский узел разбивается или к которым ведет. Вы можете увидеть дендрограмму здесь.

Словарь из загрузки json-файла выглядит так:

{'node_attributes': [{'height': 0.8416,
   'members': 290,
   'edgePar.col': '#000000',
   'edgePar.lwd': 2,
   'edgePar.conf': 1,
   'label': '',
   'midpoint': 256.4472,
   'cell_set_accession': 'CS1910120323',
   'cell_set_alias': '',
   'cell_set_designation': 'Neuron/Non-Neuron',
   'X': '291',
   'node_id': 'n1'}],
 'children': [{'node_attributes': [{'height': 0.6271,
     'members': 279,
     'edgePar.col': '#000000',
     'edgePar.lwd': 2,
     'edgePar.conf': 1,
     'label': '',
     'midpoint': 226.7537,
     'cell_set_accession': 'CS1910120324',
     'cell_set_alias': '',
     'cell_set_designation': 'Neuron/Non-Neuron',
     'X': '292',
     'node_id': 'n2'}],
   'children': [{'node_attributes': [{'height': 0.365,
       'members': 271,
       'edgePar.col': '#000000',
       'edgePar.lwd': 2,
       'edgePar.conf': 1,
       'label': '',
       'midpoint': 178.695,
       'cell_set_accession': 'CS1910120325',
       'cell_set_alias': '',
       'cell_set_designation': 'Neuron 001-271',
       'X': '293',
       'node_id': 'n3'}],............

а также dictionary['children'][0] следует за левым разделением, и если в узле есть два разделения, dictionary['children'][1] следует за правым расколом.

Я хочу, чтобы форма вывода была примерно такой:

{n1 : [n2, n281],
 n2 : [n3, n284],...}

На данный момент я просто могу разобрать словарь и вернуть узлы, используя код, адаптированный из другого сообщения:

def walk(d):

    for k,v in d.items():
        if isinstance(v, str) or isinstance(v, int) or isinstance(v, float):
            if k == 'node_id':
                print('node:', v)
        elif isinstance(v, list):
            for v_int in range(len(v)):
                walk(v[v_int])

walk(dend)

Output:
node: n1
node: n2
node: n3
node: n4
node: n183
node: n184
node: n185

1 ответ

Решение

Это может быть близко к тому, что вы хотите.

https://github.com/danielsf/AllenInstTools_by_SFD/blob/master/parse_dendrogram.py

Создает класс CellNode который хранит для каждого узла в дендрограмме имя (cell_set_accession) узла, а также списки имен всех предков, дочерних элементов (непосредственные дочерние элементы) и конечных дочерних элементов (все узлы, произошедшие от текущего узла) в дереве. Методbuild_tree вернет диктовку на cell_set_accession, значениями которого являются CellNode для этого узла.

Если вам не нравится использовать cell_set_accession в качестве имени узлов вы можете изменить его в строке 120 сценария.

Если вы хотите, чтобы в вашем dict было больше или меньше информации, вы можете идентифицировать листовые узлы, потому что они будут возвращать пустые списки для node.children.

Код был достаточно хорош для моих целей (это хороший способ сказать, что я его тщательно не тестировал). Не стесняйтесь обращаться, если что-то не работает должным образом.

Другие вопросы по тегам