Как быстро найти прямоугольник, содержащий его для каждой точки в pyspark - PullRequest
0 голосов
/ 18 апреля 2019

У меня есть фрейм данных с именем grid_df, который содержит много координат прямоугольников. И еще один фрейм данных под названием trajectory_df, который содержит много точечных координат.

from pyspark.sql import SparkSession

sqlContext = SparkSession.builder.master("local").appName("test").enableHiveSupport().getOrCreate()
data = [(0,0,0,5,5),(1,0,3,5,8)]
grid_df = sqlContext.createDataFrame(data, schema=['grid_id','lat_min','lng_min','lat_max','lng_max'])

data = [(0,1,1,),(1,2,2),(2, 4, 3),(3, 7, 4)]
trajectory_df = sqlContext.createDataFrame(data, schema=['point_id','lng','lat'])

Данные показывают:

+-------+-------+-------+-------+-------+
|grid_id|lat_min|lng_min|lat_max|lng_max|
+-------+-------+-------+-------+-------+
|      0|      0|      0|      5|      5|
|      1|      0|      3|      5|      8|
+-------+-------+-------+-------+-------+

+--------+---+---+
|point_id|lng|lat|
+--------+---+---+
|       0|  1|  1|
|       1|  2|  2|
|       2|  4|  3|
|       3|  7|  4|
+--------+---+---+

Я хочу найти прямоугольник, содержащий его для каждой координатной точки. Я ожидаю, что результат будет следующим. new_list представляет идентификатор прямоугольника grid_id, который содержит точку.

+--------+---+---+--------+
|point_id|lng|lat|new_list|
+--------+---+---+--------+
|       0|  1|  1|     [0]|
|       1|  2|  2|     [0]|
|       2|  4|  3|  [0, 1]|
|       3|  7|  4|     [1]|
+--------+---+---+--------+

В моих реальных данных тысячи записей в grid_df и сотни миллионов в trajectory_df. У меня в Google много информации, например ГИС с pySpark: непростое путешествие и PySparkGeoAnalysis . Но я не нашел решения, потому что эти методы применяют прямоугольник или не поддерживают pyspark.

Надеюсь, решение достаточно быстрое. Заранее спасибо.

1 Ответ

1 голос
/ 18 апреля 2019

Использование join может быть дорогостоящей операцией, так как вы упомянули, что trajectory_df имеет много точек. Тем не менее, скорость вычислений можно объяснить размером кластера в искре.

#Logic here is lat should be between lat_min and lat_max. Similar condition for lng too.
>>> grid_df.join(trajectory_df,((trajectory_df.lat>=grid_df.lat_min) & (trajectory_df.lat<=grid_df.lat_max) & (trajectory_df.lng>=grid_df.lng_min) & (trajectory_df.lng<=grid_df.lng_max))).groupBy(trajectory_df.point_id).agg(F.collect_list("grid_id").alias("grid_id")).show()
+--------+-------+
|point_id|grid_id|
+--------+-------+
|       0|    [0]|
|       1|    [0]|
|       3|    [1]|
|       2| [0, 1]|
+--------+-------+

Попробуй!

...