Есть ли способ добавить кортеж position в качестве атрибута к созданному узлу в networkx?

#python-3.x #parsing #graph #networkx

#python-3.x #синтаксический анализ #График #networkx

Вопрос:

Я пытаюсь получить положение всех узлов, которые создаются в моем графике. Текущая цель состоит в том, чтобы создать все узлы, которые обладают координатами x и y .

То, что я читал, касается атрибутов при использовании add_nodes_from() и, возможно, создания атрибута position для моих узлов. Чтение небольшой документации и другого StackOverflow для меня не увенчались успехом.

ex.txt файл:

 a2a 5 0
##start
a0 1 2
##end
a1 9 2
3 5 4
  

файл python:

 import re
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt

def file_parsing(file_path):
    cnt = 0
    output_list = []

    with open(file_path, 'r') as fp:
        for line in fp:
            cnt  = 1
            #checks for the room name and coordinates
            if re.match('([^s#]{1,10}) (d ) (d )', line, re.MULTILINE):
                output_list.append(line.strip().split(' '))
            #checks for start
            if line.startswith('##start'):
                output_list.append(next(fp, '').strip().split())
            #checks for start
            if line.startswith('##end'):
                output_list.append(next(fp, '').strip().split())
    room_name = [item[0] for item in output_list]
    x_coord = [int(item[1]) for item in output_list]
    y_coord = [int(item[2]) for item in output_list]
    x_y = list(zip(x_coord, y_coord))
    return (room_name, output_list, x_y)

rooms, room_coords, xpos_ypos = file_parsing('ex.txt')
print("Room information: ", room_coords)
print("X and Y position as tuple list: ", xpos_ypos)
DG = nx.DiGraph()
DG.add_nodes_from(rooms, pos = xpos_ypos)
pos = nx.get_node_attributes(DG, 'pos')
print(pos)

plt.figure()

nx.draw_networkx(DG)
  

Как вы видите, у меня есть мой xpos_ypos в zip-файле, который создает список кортежей. И мой порядок итерации имеет значение, потому что первая комната будет иметь координаты x и y из первого кортежа.

Например, моя первая комната — это, a2a которая будет иметь координату (5, 0) . Комната a0 будет иметь координаты, если (1, 2) . Теперь, если я хочу делать одно и то же снова и снова для каждой комнаты: как я мог бы добавить атрибуты координат комнаты к каждой комнате? В моем случае в результате я получаю словарь:

{'a2a': [(5, 0), (1, 2), (9, 2), (5, 4)], 'a0': [(5, 0), (1, 2), (9, 2), (5, 4)], 'a1': [(5, 0), (1, 2), (9, 2), (5, 4)], '3': [(5, 0), (1, 2), (9, 2), (5, 4)]}

и это результат draw_networkx(DG) : орграф

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

1. nx.draw принимает аргумент pos — try : nx.draw_networkx(DG,pos=pos)

2. Я уже пробовал это раньше, и я получаю сообщение об ошибке ValueError: too many values to unpack (expected 2) @JohannesWachs

Ответ №1:

Ваш код не работает, потому что вы неправильно передаете позиции. Я внес несколько изменений в вашу функцию, чтобы она возвращала словарь с ключами в качестве имен узлов и значениями в качестве [x, y] координат. Что-то вроде этого

 {'a2a': (5, 0), 'a0': (1, 2), 'a1': (9, 2), '3': (5, 4)}
  

Затем я создал график из возвращенного словаря и приведенного выше словаря к pos атрибуту nx.draw_networkx функции.

 import re
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
%matplotlib inline
def file_parsing(file_path):
    cnt = 0
    output_list = []

    with open(file_path, 'r') as fp:
        for line in fp:
            cnt  = 1
            #checks for the room name and coordinates
            if re.match('([^s#]{1,10}) (d ) (d )', line, re.MULTILINE):
                output_list.append(line.strip().split(' '))
            #checks for start
            if line.startswith('##start'):
                output_list.append(next(fp, '').strip().split())
            #checks for start
            if line.startswith('##end'):
                output_list.append(next(fp, '').strip().split())
    room_name = [item[0] for item in output_list]
    x_coord = [int(item[1]) for item in output_list]
    y_coord = [int(item[2]) for item in output_list]
    x_y = list(zip(x_coord, y_coord))

    #--------------Changes start from here -----------#

    pos_dict = dict(zip(room_name, x_y))
    return pos_dict

room_pos_dict = file_parsing('ex.txt')
G = nx.Graph()
G.add_nodes_from(room_pos_dict.keys())
nx.set_node_attributes(G, room_pos_dict, 'pos')
nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'))
  

введите описание изображения здесь

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

1. Спасибо за ваш ответ. Я пытался соединить узлы вместе, используя add_edges_from() от узла к узлу, где их положение совпадает с вашим. Я пробовал отдельно с кодом, который у меня уже есть, без позиционирования узлов, но пока безуспешно. Например, мой nome a0 должен соединяться с узлами 3 и a2a . В вашем примере, как бы я справился с подключением узлов вместе со словарем, который уже создан?

2. Добро пожаловать! Не могли бы вы, пожалуйста, создать отдельный вопрос, поскольку ваш первоначальный вопрос был только об исходном расположении узлов, и этот ответ решает эту проблему 🙂 Кроме того, если этот ответ помог вам, не могли бы вы, пожалуйста, пометить его как правильный. В вашем новом вопросе также упомяните о том, как считывать ребра из файла, который у вас есть, т.Е. ex.txt .