#apache-spark #dataframe #graph #tree #hierarchy
#apache-spark #фрейм данных #График #дерево #иерархия
Вопрос:
Рассмотрим дерево и его представление фрейма данных (левая таблица):
0 ┌───────┬───────┐ ┌───────┬───────┐
├──1 │ id │ parent│ │ id │ path │
│ ├──2 ├───────┼───────┤ ├───────┼───────┤
│ └──3 │ 5 │ 0 │ │ 5 │0/5 │
│ └──4 ├───────┼───────┤ ├───────┼───────┤
└──5 │ 4 │ 3 │ │ 4 │0/1/3/4│
├───────┼───────┤ => ├───────┼───────┤
│ 3 │ 1 │ │ 3 │0/1/3 │
├───────┼───────┤ ├───────┼───────┤
│ 2 │ 1 │ │ 2 │0/1/2 │
├───────┼───────┤ ├───────┼───────┤
│ 1 │ 0 │ │ 1 │0/1 │
├───────┼───────┤ ├───────┼───────┤
│ 0 │ null │ │ 0 │0 │
└───────┴───────┘ └───────┴───────┘
Каков наиболее эффективный способ получить древовидный путь (начиная с корня) для каждого узла дерева (правой таблицы)?
Разрешены все возможные методы: SQL-запросы, методы фрейма данных, GraphX и т. Д.
Примечание: классическое решение SQL с рекурсивными объединениями не будет работать для фреймов данных Spark.
Комментарии:
1. Я подозреваю, что GraphX был бы правильным решением, но я сомневаюсь, что это было бы очень эффективно.
2. Да, кажется, эта задача может быть решена без инициализации графика.
3. @OlegMikhailov, как насчет RDD
mapPartitions
?4. @Sai, все методы хороши, пока они эффективны
Ответ №1:
Это похоже на задачу API Spark Graph. Вы можете посмотреть на пакет spark Graphframes. Это пакет, который предоставляет высокоуровневые API-интерфейсы поверх ядра GraphX (то же самое используется в традиционных фреймах данных Spark поверх RDDS). С помощью этого вы можете строить графики с вашими фреймами данных.
Посмотрите на эту ссылку: https://mapr.com/blog/analyzing-flight-delays-with-apache-spark-graphframes-and-mapr-db /
Он показывает вариант использования с данными о рейсах. Если вы посмотрите на Breadth First Search Graph Algorithm
раздел, вы увидите алгоритм, который делает именно то, что вы хотите: нахождение пути между двумя вершинами (с учетом параметра maxPathLength).
Запустите pyspark с зависимостями graphframes (в соответствии с вашей версией spark):
pyspark --packages graphframes:graphframes:0.6.0-spark2.3-s_2.11
Построение вашего фрейма данных:
df = sc.parallelize([{"id": 5, "parent": 0}, {"id": 4, "parent": 3}, {"id": 3, "parent": 1}, {"id": 2, "parent": 1}, {"id": 1, "parent": 0}, {"id": 0, "parent": None}]).toDF()
Создание графика:
df_vertices = df.selectExpr("id")
df_edges = df.withColumnRenamed("id", "dst").withColumnRenamed("parent", "src")
from graphframes import GraphFrame
graph = GraphFrame(df_vertices, df_edges)
Визуализируйте путь (например, от 0 до 4):
graph.bfs(fromExpr="id = 0",toExpr="id = 4", maxPathLength=10).show(2)
Результат:
---- ------ --- ------ --- ------ ---
|from| e0| v1| e1| v2| e2| to|
---- ------ --- ------ --- ------ ---
| [0]|[1, 0]|[1]|[3, 1]|[3]|[4, 3]|[4]|
---- ------ --- ------ --- ------ ---