Анализ связности направленного графа с библиотекой Networkx в Google Colab

Автор Категория ,
Анализ связности направленного графа с библиотекой Networkx в Google Colab

В рамках продвижения нашего нового курса по графовой аналитике больших данных в бизнес-приложениях, сегодня рассмотрим, что такое связность в графе, зачем вычислять компоненты связности и как это сделать для ориентированных графов. Продемонстрируем все вычисления с помощью методов Python-библиотеки Networkx в Google Colab.

Основы теории графов и применения Networkx в Google Colab на практическом примере

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

Рассмотрим этот пример более подробно. Предположим, есть данные за сутки по переходам пользователей сайта: со страниц корпоративного блога на страницы продаваемых продуктов – образовательных курсов, а также между страницами блога. Входной точкой чаще всего является страница блога, куда пользователь пришел по ключевым словам в поисковом запросе, а затем перешел на страницу курса. Фрагмент датасета представлен на рисунке, где столбец node1 – это исходная страница блога, node2 – последующая страница курса или блога, а edge – количество переходов.

Построим направленный (ориентированный) взвешенный граф по этим переходам с помощью Python-библиотеки Networkx в Google Colab. Эта библиотека написана на Python и свободно распространяется под лицензией BSD. Она предназначена для создания, манипуляции и анализа структуры, динамики и функционирования графовых структур. Хотя NetworkX имеет базовые функции визуализации графов, основная цель этого инструмента – анализ графов, а не визуализация. Поэтому для наглядного отображения графов рекомендуется использовать специализированные библиотеки, например, Matplotlib. Для этого ее следует также, как и NetworkX, импортировать в свой Python-скрипт. Если исходные данные для построения графа содержатся в списке, его следует преобразовать в датафрейм pandas, чтобы создать взвешенный граф из этого датафрейма. Таким образом, также необходим импорт библиотеки Pandas. Код на Python в Google Colab будет выглядеть так:

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

data = [('Blog_Page_1','COURSE_1',90),('Blog_Page_1','COURSE_2',212),('Blog_Page_1','Blog_Page_2',99),('Blog_Page_6','COURSE_1',58),
        ('Blog_Page_3','COURSE_4',401),('Blog_Page_3','COURSE_2',2),('Blog_Page_6','Blog_Page_2',309),('Blog_Page_1','COURSE_3',306),
        ('Blog_Page_3','Blog_Page_2',41),('Blog_Page_11','COURSE_1',122),('Blog_Page_2','Blog_Page_6',39),('Blog_Page_2','COURSE_4',224),
        ('Blog_Page_11','COURSE_3',201),('Blog_Page_11','COURSE_4',89),('Blog_Page_6','Blog_Page_3',309),('Blog_Page_1','Blog_Page_3',76)
        ]
df = pd.DataFrame(data=data,columns=['node1','node2','edge'])

graph=nx.DiGraph()
graph.add_weighted_edges_from(data)
pos = nx.spring_layout(graph, k=1000)
nx.draw(graph, pos, with_labels=True)
plt.show()
NetworkX dataframe Google Colab graph
Направленный граф, построенный с помощью библиотеки NetworkX

Как проанализировать этот граф и вычислить его связность, рассмотрим далее.

Анализ связности графа

Связным называется граф, который содержит ровно одну компоненту связности, т.е. между любой парой его вершин существует как минимум один путь. В контексте одного узла вычисляют степень связности – число связей, инцидентных узлу, т.е.  количество его ребер. В направленном графе определяются две меры степени связности: полустепень захода (число связей, входящих в узел) и полустепень исхода (число связей, исходящих из узла). Например, если рассматривать связь как дружбу или сотрудничество, полустепень захода показывает популярность человека, а полустепень исхода – его общительность. Это полезно при анализе социальных связей, о чем мы писали здесь.

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

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

Ответить на вопрос, является ли рассматриваемый граф сильно связным или слабо связным, помогут соответствующие методы библиотеки NetworkX: is_strongly_connected(G) и  is_weakly_connected(G), которые возвращают значения True или False. В качестве параметра G следует указать имя графа. Также рассчитаем количество сильно и слабо связных компонентов в графе с помощью методов nx.number_strongly_connected_components(G) и nx.number_ weakly _connected_components(G). Еще выведем самый большой сильный и самый большой слабый связные компоненты исходного графа.

print('\nИсходный граф является сильно связным?', nx.is_strongly_connected(graph))
print('число сильно связных компонентов в исходном графе = ', nx.number_strongly_connected_components(graph))
print('Сильно связные компоненты = ', max(nx.strongly_connected_components(graph), key=len))

print('\nИсходный граф является слабо связным?', nx.is_weakly_connected(graph))
print('число слабосвязных компонентов в исходном графе = ', nx.number_weakly_connected_components(graph))
print('Слабо связные компоненты ', max(nx.weakly_connected_components(graph), key=len))

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

length, path = nx.single_source_dijkstra(graph, source='Blog_Page_1', target='COURSE_4')
print('Вес пути (число кликов) из страницы блога Blog_Page_1 на страницу курса COURSE_4 = ', length)
print('Путь из страницы блога Blog_Page_1 на страницу курса COURSE_4: ', path)
анализ графов, связность графа, NetworkX dataframe Google Colab graph
Результаты анализа графа с NetworkX в Google Colab

С практической точки зрения рассмотренные приемы анализа пользовательских переходов по страницам сайта пригодятся для увеличения вовлеченности клиента (рост длительности сессии), а также помогут оптимизировать путь клиента к конверсионным целям. В частности, поставить на некоторых информационных страницах сайта (страницы блога) баннеры с перелинковкой на страницы продукта (образовательного курса), формы обратной связи для отправки заявки и прочие мероприятия, направленные на рост конверсии.

Как применить инструменты графовой аналитики больших данных для своих бизнес-задач, вы узнаете на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков больших данных в Москве:

Я даю свое согласие на обработку персональных данных и соглашаюсь с политикой конфиденциальности.

Источники

  1. https://www.geeksforgeeks.org/find-weakly-connected-components-in-a-directed-graph
  2. https://www.programiz.com/dsa/strongly-connected-components
  3. https://networkx.org/documentation/stable/reference/algorithms/component.html
  4. https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.shortest_paths.weighted.single_source_dijkstra.html