Вопрос или проблема
С помощью pyvis
и networkx
я хочу создать сеть по приведенному ниже набору данных и коду. Метки данных на ребрах должны использовать столбец “Label”.
Однако метки данных перепутаны. Например, ребро от Майка к Тому должно показывать 925, но показывает 2.
Где была допущена ошибка?
import pandas as pd
import networkx as nx
from pyvis.network import Network
import os
from io import StringIO
csvfile = StringIO(
"""Source Target Weight Label
Kate Viki 0 1
Kate Lilly 0.06 16
Kate Kate 0.09 22
Kate Tom 0.30 71
Mike Lilly 0.04 2
Mike Kate 1.02 239
Mike Tom 3.99 925
Tom Lilly 0.04 2
Tom Frank 0 1
Tom Kate 0.12 30
Tom Tom 0.03 8
""")
df = pd.read_csv(csvfile, sep = '\t', engine="python")
G = nx.from_pandas_edgelist(df, source="Source", target="Target", edge_attr="Weight")
label_values = df['Label'].tolist()
for i, edge in enumerate(G.edges(data=True)):
edge[2]['label'] = str(label_values[i]) # Назначаем случайный номер в качестве метки ребру
net = Network(notebook=True)
net.from_nx(G)
# Устанавливаем ширину ребер в зависимости от весов
for edge in net.edges:
edge['width'] = edge['Weight'] # Устанавливаем ширину ребра в зависимости от его веса
# Устанавливаем видимость меток ребер и размер шрифта
for edge in net.edges:
edge['label'] = edge['label']
edge['font'] = {'size': 14}
output_file = "test-.html"
net.show(output_file)
Ответ или решение
Ваша задача заключается в том, чтобы правильно установить метки для ребер в графе, используя библиотеки pyvis
и networkx
. Рассмотрим код, представленный вами, и укажем, где именно возникает ошибка.
Анализ кода
Основная проблема в вашем коде заключается в том, что метки для ребер устанавливаются неправильно из-за того, как вы извлекаете их из DataFrame. При использовании G.edges(data=True)
в цикле for
вы назначаете метки в зависимости от индекса каждой стороны, что в результате приводит к неправильному соответствию между метками и ребрами.
Правильное решение
Чтобы исправить это, вместо использования индекса ребер, вам следует извлекать метки непосредственно из DataFrame на основе значений Source
и Target
каждого ребра. Ниже приведена исправленная версия вашего кода, где метки для ребер назначаются правильно:
import pandas as pd
import networkx as nx
from pyvis.network import Network
from io import StringIO
# Исходные данные
csvfile = StringIO(
"""Source Target Weight Label
Kate Viki 0 1
Kate Lilly 0.06 16
Kate Kate 0.09 22
Kate Tom 0.30 71
Mike Lilly 0.04 2
Mike Kate 1.02 239
Mike Tom 3.99 925
Tom Lilly 0.04 2
Tom Frank 0 1
Tom Kate 0.12 30
Tom Tom 0.03 8
""")
# Чтение данных в DataFrame
df = pd.read_csv(csvfile, sep='\s+')
# Создание графа из DataFrame
G = nx.from_pandas_edgelist(df, source="Source", target="Target", edge_attr=["Weight", "Label"])
# Создание объекта Network из pyvis
net = Network(notebook=True)
# Добавление графа в pyvis
net.from_nx(G)
# Установка ширины ребер на основе весов
for edge in net.edges:
edge['width'] = edge['Weight'] # Установка ширины ребра
# Установка видимости меток и размера шрифта для меток
for edge in net.edges:
edge['label'] = edge['Label'] # Установка меток на ребрах
edge['font'] = {'size': 14}
# Сохранение результата в HTML файл
output_file = "test-.html"
net.show(output_file)
Объяснение изменений
-
Использование
edge_attr=["Weight", "Label"]
: Теперь мы загружаем как вес, так и метку для каждого ребра в графG
. -
Изменение присвоения меток: Вместо того чтобы присваивать метки на основании индекса
i
, мы используем значение метки, загруженное в таблицу графа, гарантируя, что каждая метка соответствует своему ребру.
Заключение
Теперь при выполнении исправленного кода метки на ребрах должны отображаться корректно, согласно значениям из вашего DataFrame. Убедитесь, что при визуализации в HTML граф действительно показывает правильные метки для всех ребер.