@holllop

Как улучшить выводимый граф?

Хочу сделать граф более понятным и чтобы визуального его проще было воспринимать. Да я прекрасно понимаю что такие данные лучше подавать в виде какой-то матрицы или чело-то подобного, но всё же хочется подать информацию в виде графа, если это возможно.
Скрипт, который создаёт граф
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt

def read_excel_data(filepath):
    pairs = pd.read_excel(filepath, sheet_name='Pair Count')
    triples = pd.read_excel(filepath, sheet_name='Triple Count')
    quads = pd.read_excel(filepath, sheet_name='Quadruple Count')

    return pairs, triples, quads

def create_probability_graph(pairs, triples, quads):
    G = nx.DiGraph()

    # Добавляем узлы и ребра для пар
    for _, row in pairs.iterrows():
        first_letter = row['Первая буква']
        second_letter = row['Вторая буква']

        conditional_probability = row['Условная вероятность']
        G.add_edge(first_letter, second_letter, weight=conditional_probability, label=f"{conditional_probability:.2%}")

    # Добавляем узлы и ребра для троек
    for _, row in triples.iterrows():
        first_letter = row['Первая буква']
        second_letter = row['Вторая буква']
        third_letter = row['Третья буква']

        conditional_probability = row['Условная вероятность']
        G.add_edge(second_letter, third_letter, weight=conditional_probability, label=f"{conditional_probability:.2%}")

    # Добавляем узлы и ребра для четверных комбинаций
    for _, row in quads.iterrows():
        first_letter = row['Первая буква']
        second_letter = row['Вторая буква']
        third_letter = row['Третья буква']
        fourth_letter = row['Четвертая буква']

        conditional_probability = row['Условная вероятность']
        G.add_edge(third_letter, fourth_letter, weight=conditional_probability, label=f"{conditional_probability:.2%}")

    return G

def visualize_graph(G):
    pos = nx.spring_layout(G)  # Используем алгоритм spring_layout с увеличением расстояния между узлами
    edge_labels = nx.get_edge_attributes(G, 'label')

    plt.figure(figsize=(30, 30))  # Увеличиваем размер фигуры
    nx.draw(G, pos, with_labels=True, node_size=1000, node_color='skyblue', font_size=10, font_weight='bold')
    nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_color='red', font_size=10, bbox=dict(facecolor='yellow', edgecolor='black', boxstyle='round,pad=0.3'))

    plt.title('Probability Tree Graph', fontsize=30)
    plt.show()

if __name__ == "__main__":
    input_file = "pair_triple_quad_output.xlsx"

    # Читаем данные из Excel
    pairs, triples, quads = read_excel_data(input_file)

    # Создаем граф
    G = create_probability_graph(pairs, triples, quads)

    # Визуализируем граф
    visualize_graph(G)

получаю вот такой граф
665029431feba500645147.png
и тут не разобрать всю эту путаницу из рёбер. Возможно ли улучшить визуально граф или это не возможно из-за количества точек и рёбер ?
ниже так же приведу код который я так же пробовал
spoiler
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt

def read_excel_data(filepath):
    pairs = pd.read_excel(filepath, sheet_name='Pair Count')
    triples = pd.read_excel(filepath, sheet_name='Triple Count')
    quads = pd.read_excel(filepath, sheet_name='Quadruple Count')

    return pairs, triples, quads

def create_probability_graph(pairs, triples, quads):
    G = nx.DiGraph()

    # Добавляем узлы и ребра для пар
    for _, row in pairs.iterrows():
        first_letter = row['Первая буква']
        second_letter = row['Вторая буква']

        conditional_probability = row['Условная вероятность']
        G.add_edge(first_letter, second_letter, weight=conditional_probability, label=f"{conditional_probability:.2%}")

    # Добавляем узлы и ребра для троек
    for _, row in triples.iterrows():
        first_letter = row['Первая буква']
        second_letter = row['Вторая буква']
        third_letter = row['Третья буква']

        conditional_probability = row['Условная вероятность']
        G.add_edge(second_letter, third_letter, weight=conditional_probability, label=f"{conditional_probability:.2%}")

    # Добавляем узлы и ребра для четверных комбинаций
    for _, row in quads.iterrows():
        first_letter = row['Первая буква']
        second_letter = row['Вторая буква']
        third_letter = row['Третья буква']
        fourth_letter = row['Четвертая буква']

        conditional_probability = row['Условная вероятность']
        G.add_edge(third_letter, fourth_letter, weight=conditional_probability, label=f"{conditional_probability:.2%}")

    return G

def visualize_graph(G):
    pos = nx.spring_layout(G, k=4, iterations=100, scale=3) # Увеличиваем значение параметра k для увеличения расстояния между узлами(пробовал различные цифры для параметров k, iterations, scale особо каких-то оптимальных не нашёл)  
    edge_labels = nx.get_edge_attributes(G, 'label')

    plt.figure(figsize=(20, 20))
    nx.draw(G, pos, with_labels=True, node_size=3000, node_color='skyblue', font_size=12, font_weight='bold')
    nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_color='red', font_size=8, bbox=dict(facecolor='yellow', edgecolor='black', boxstyle='round,pad=0.3'))

    plt.title('Probability Tree Graph', fontsize=20)
    plt.show()

if name == "main":
    input_file = "pair_triple_quad_output.xlsx"

    # Читаем данные из Excel
    pairs, triples, quads = read_excel_data(input_file)

    # Создаем граф
    G = create_probability_graph(pairs, triples, quads)

    # Визуализируем граф
    visualize_graph(G)
  • Вопрос задан
  • 107 просмотров
Пригласить эксперта
Ответы на вопрос 3
Maksim_64
@Maksim_64
Data Analyst
Networkx - крутая библиотека, но графики это не ее основное направление, вся суть Networkx это интерфейс для алгоритмов, связанных с графами, визуализация лишь приятный бонус.

Подобная история весьма распростронена для python экосистемы, например stasmodels (статистические модели) тоже имеет визуализацию и тоже matplotlib в качестве бэкенда, sympy крутейшая библиотека для работы с математическими выражениями тоже имеет в дополнение визуализацию и тоже matpltolib в качестве бэка.

У подобных кейсов возможности визуализаций крайне ограничены.

Тебе нужно организовывать визуализацию самостоятельно, то есть получить данные как структуры данных и визуализировать их. Посмотри в сторону networkx + plotly.

plotly из коробки имеет огромное количество эффектов которые улучшат читабельность графа, зум можно будет легко добавить и иные эффекты. Matplotlib все это тоже позволяет, просто с позиции реализации это на много сложнее.

гугли примеры networkx + plotly и стратегия твоя это визуализация не средствами networkx а средствами сторонней библиотеки, я предложил plotly с позиции временных затрат на реализацию.
Ответ написан
trapwalker
@trapwalker Куратор тега Python
Программист, энтузиаст
Готовых инструментов не предложу, но для "поиграться" можно попробовать сделать релаксационную модель с отжигом.
Набрасываете узлы рандомно, потом эмпирически подбираете функции сил отталкивания между узлами и узлами и рёбрами. Узлы сами будут стремиться занять распределенные положения в стороне от рёбер и других узлов. дальше можно искать новые положения для отдельных узлов, чтобы понизить число пересечений ребер.
Ещё можно использовать роевые или генетические алгоритмы для поиска расстановки узлов с минимальным самопересечением в графе. Не удивлюсь, если кто-то такими вещами уже озадачивался и можно поискать готовые решения.
Ответ написан
Комментировать
@holllop Автор вопроса
Максим Припадчев, выражаю огромную благодарность, вы меня привели к ответу. Я принял решение разделить данные на 4 графа. 1. Граф для двойных комбинаций. 2. Граф для тройных комбинаций. 3. Граф для четверных комбинаций. 4. Общий граф(изначальный вариант). Такое решение я принял, чтобы сохранить баланс между полнотой картины и наглядностью. Когда закончу полностью код оставлю его ниже(осталось не много поиграться с получаемой картинкой.)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
SpectrumData Екатеринбург
от 150 000 до 200 000 ₽
Гринатом Москва
от 150 000 ₽
Greenway Global Новосибирск
от 150 000 ₽
16 июн. 2024, в 20:43
90909 руб./за проект
16 июн. 2024, в 19:56
30000 руб./за проект