Графовая аналитика путешествий цифровых кочевников с Neo4j и Cypher

Автор Категория , ,
Графовая аналитика путешествий цифровых кочевников с Neo4j и Cypher

В рамках продвижения нашего нового курса по графовой аналитике больших данных в бизнес-приложениях, сегодня рассмотрим пример анализа данных о путешествиях средствами графовой СУБД Neo4j и ее языка запросов Cypher. Читайте далее, где взять данные о путешествиях цифровых кочевников и как определить самое популярное направление.

Цифровые кочевники и графы их путешествий

Хотя пандемия COVID-19 сильней всего ударила по сфере туризма, люди все равно продолжают путешествовать по разным городам и странам. А устойчивый тренд на дистанционную работу позволяет знакомиться с новыми местами не только в отпуске. Людей, которые путешествуют по планете, удаленно работая из любой точки мира, называют цифровыми кочевниками (digital nomad). Последователи этого образа жизни образуют собственные сообщества, обмениваясь опытом и полезными советами о разных локациях. Одним из инструментов для этого является сайт NomadList.com, где также имеются обезличенные данные о путешествиях в виде логов за 2014-2021 гг. по 50 наиболее популярным городам. Их можно проанализировать с помощью графовых алгоритмов, которые отлично подходят для логистических задач. Граф путешествий можно представить следующим образом:

  • город – это узел;
  • путешествие – это перемещение между городами, т.е. ребро графа, которое соединяет 2 узла. Логи путешествий описывают отношения между узлами, например, расстояние или стоимость перемещения.

Таким образом, мы имеем дело с ориентированным взвешенным графом.

графовые алгоритмы, графовая аналитика больших данных пример курсы обучение
Граф путешествий

Сперва следует определить уникальное ограничение свойства для узлов, чтобы гарантировать уникальное значение конкретной метки для каждого города. Также в Neo4j это автоматически добавляет индекс по этому полю для более быстрого импорта и запросов. Обычно таким уникальным свойством является идентификатор (id).

Напомним, Cypher – это язык запросов в Neo4j, оптимизированный для графов, который определяет и использует отношения данных. Он исследует взаимосвязи во всех направлениях. Команды Cypher похожи на SQL, но иногда отличаются. Следующая команда на Cypher позволит задать ограничение по уникальному идентификатору для городов.

CREATE CONSTRAINT ON (c:City) ASSERT c.id IS UNIQUE;

Чтобы импортировать логи поездок с сайта NomadList в формате JSON, можно использовать процедуру apoc.load.json для получения данных со страницы и процедуру apoc.periodic.iterate для пакетной обработки полученных данных.

CALL apoc.periodic.iterate(‘

CALL apoc.load.json(“https://nomadlist.com/graph.json”)

YIELD value

WITH value, [x in keys(value) WHERE x <> “README” | x] AS keys

UNWIND keys AS source_city

WITH source_city, value

RETURN source_city, value

‘,’

MERGE (s:City{name:source_city})

WITH value[source_city] as destinations, s

WHERE destinations <> []

WITH destinations, keys(destinations) as destination_cities, s

UNWIND destination_cities AS destination_city

MERGE (t:City{name:destination_city})

MERGE (s)-[r:TRAVEL_TO]->(t)

SET r.weight = destinations[destination_city]’,

{batchSize:10})

Расстояние между городами отсутствует в исходном наборе данных, но их можно добавить самостоятельно, используя пространственные процедуры APOC для определения местоположения GPS или взять CSV-файл со всеми локациями городов с GitHub.

LOAD CSV WITH HEADERS FROM

“https://raw.githubusercontent.com/tomasonjo/blog-datasets/main/nomad/nomad_cities_location.csv” as row

MATCH (c:City)

WHERE c.name = row.city

SET c.location = point({latitude:toFloat(row.latitude),

longitude:toFloat(row.longitude)})

После этого можно вычислить расстояние между городами на основе данных об их местоположении:

MATCH (s:City)-[r:TRAVEL_TO]->(t:City)

WITH r,distance(s.location, t.location) / 1000 AS distanceInKm

SET r.distance = distanceInKm

Анализ графов о путешествиях с Neo4j и Cypher: еще несколько примеров

Понять, сколько логов путешествий представлено на графе поможет общая сумма свойства веса для всех отношений путешествия. В отличие от SQL-оператора SELECT для просмотра данных в реляционных СУБД, в Cypher используется инструкция MATCH, которая сопоставит и вернет все узлы в базе данных. А RETURN указывает, какой результат нужен, например, сумма веса всех путешествий. 

MATCH p=()-[r:TRAVEL_TO]->()

RETURN sum(r.weight) as all_travels

Чтобы определить самые популярные направления, нужно найти узлы с наибольшим весом.

MATCH (c:City)<-[r:TRAVEL_TO]-()

RETURN c.name as city, sum(r.weight) as travels

ORDER BY travels DESC

LIMIT 10

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

MATCH ()-[r:TRAVEL_TO]->()

RETURN sum(CASE WHEN r.distance < 500 THEN r.weight END)

/ toFloat(sum(r.weight)) AS within_500,

sum(CASE WHEN 500 < r.distance < 1000 THEN r.weight END)

/ toFloat(sum(r.weight)) AS within_1000,

sum(CASE WHEN 1000 < r.distance < 2000 THEN r.weight END)

/ toFloat(sum(r.weight)) AS within_2000,

sum(CASE WHEN 2000 < r.distance THEN r.weight END)

/ toFloat(sum(r.weight)) AS rest

Таким образом, почти 50% всех зарегистрированных поездок составляют менее 1000 км. Для Европы – это ночной переезд на поезде, а 2000-километровая поездка – это примерно два часа лета на самолете. Остальные 30% путешествий, скорее всего, межконтинентальные поездки, т.к. цифровые кочевники любят путешествовать по разным странам и континентам.

Чтобы далее применить графовые алгоритмы Neo4j из библиотеки Graph Data Science, следует сперва создать граф в памяти:

CALL gds.graph.create(‘nomad’, ‘City’, ‘TRAVEL_TO’,

{relationshipProperties:’weight‘});

Выявить отдельные части, сообщества узлов или кластеры в графе поможет алгоритм слабосвязанных компонентов, запущенный следующим Cypher-запросом:

CALL gds.wcc.stats(‘nomad’)

YIELD componentCount, componentDistribution;

Определим меру связности узлов созданного в памяти графа:

CALL gds.betweenness.stream(‘nomad’)

YIELD nodeId, score

RETURN gds.util.asNode(nodeId).name AS city, score

ORDER BY score DESC LIMIT 10

Чтобы визуализировать результаты анализа, воспользуемся алгоритмом PageRank для определения размера узлов. В контексте PageRank каждое отношение можно интерпретировать как степень доверия. В примере с логами путешествий NomadList самые популярные направления должны иметь наивысший балл, поскольку алгоритм PageRank учитывает количество входящих соединений и их источник.

CALL gds.pageRank.write(‘nomad’, {relationshipWeightProperty:’weight’,

writeProperty:’pagerank‘});

Для определения цвета узлов в визуализации, будем использовать алгоритм модульности Лувена для обнаружения сообщества или кластеризации, который группирует связанные узлы.

CALL gds.louvain.write(‘nomad’, {relationshipWeightProperty:’weight’,

writeProperty:’louvain‘});

графовые алгоритмы пример обучение Neo4j и Cypher, курсы Neo4j и Cypher
Визуализация графа путешествий цифровых кочевников

Оказалось, что сообщества узлов совпадают по цвету с разными континентами. Например, узлы оранжевого цвета относятся к Северной Америке, а фиолетового – к Европе. Эти результаты можно интерпретировать как межконтинентальные путешествия, поскольку более связанные города группируются в одном сообществе. Размер узлов определяет самые популярные города на этом континенте. Например, самыми популярными направлениями путешествий по Азии стали Бангкок, Куала-Лумпур, Сингапур, Чиангмай и Чангу.

Выполнив все нужные вычисления, следует сбросить спроектированный граф, чтобы освободить память: CALL gds.graph.drop(‘nomad‘)

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

Источники

  1. https://towardsdatascience.com/analyzing-travel-logs-of-digital-nomads-with-neo4j-graph-data-science-b7a13d6ba544
  2. https://nomadlist.com/graph
  3. https://neo4j.com/docs/cypher-manual/current/