Как преобразовать фрейм данных pandas в словарь для формата Newick

#python #pandas

#python #pandas

Вопрос:

У меня есть следующий набор данных:

 import pandas as pd
df = pd.DataFrame([['root', 'b', 'a', 'leaf1'],
                   ['root', 'b', 'a', 'leaf2'],
                   ['root', 'b', 'leaf3', ''],
                   ['root', 'b', 'leaf4', ''],
                   ['root', 'c', 'leaf5', ''],
                   ['root', 'c', 'leaf6', '']],
                   columns=['col1', 'col2', 'col3', 'col4'])
 

Поскольку я не нашел способа напрямую преобразовать его в формат Newic, я хотел бы преобразовать его в словарь в следующем формате:

 node_to_children = {
    'root': {'b': 0, 'c': 0},
    'a': {'leaf1': 0, 'leaf2': 0},
    'b': {'a': 0, 'leaf3': 0, 'leaf4': 0},
    'c': {'leaf5': 0, 'leaf6': 0}
}
 

Затем я могу в конечном итоге преобразовать этот node_to_children в формат Newic, однако, как я могу выполнить преобразование из фрейма данных pandas в dictionary?

Комментарии:

1. Формат дерева Newick в конечном итоге выглядит как эта строка (не те же данные из примера): ‘((B:0.2 ,(C:0.3 ,D:0.4 )E:0.5 )A:0.1 )F;’ он используется для построения графиков деревьев. Я пытаюсь построить иерархическую древовидную структуру из данных.

Ответ №1:

Я предположил, что каждая строка в вашем фрейме данных обозначает одну полную ветвь дерева от корня до листьев. Исходя из этого, я пришел к следующему решению. Комментарии к каждому шагу алгоритма можно найти в приведенном ниже коде, но не стесняйтесь спрашивать, если что-то неясно.

 node_to_children = {}

#iterate over dataframe row-wise. Assuming that every row stands for one complete branch of the tree
for row in df.itertuples():
    #remove index at position 0 and elements that contain no child ("")
    row_list = [element for element in row[1:] if element != ""]
    for i in range(len(row_list)-1):
        if row_list[i] in node_to_children.keys():
            #parent entry already existing 
            if row_list[i 1] in node_to_children[row_list[i]].keys():
                #entry itself already existing --> next
                continue
            else:
                #entry not existing --> update dict and add the connection
                node_to_children[row_list[i]].update({row_list[i 1]:0})
        else:
            #add the branching point
            node_to_children[row_list[i]] = {row_list[i 1]:0}
   
 

Вывод:

 print(node_to_children)
        
{'root': {'b': 0, 'c': 0}, 
 'b': {'a': 0, 'leaf3': 0, 'leaf4': 0}, 
 'a': {'leaf1': 0, 'leaf2': 0}, 
 'c': {'leaf5': 0, 'leaf6': 0}}