H3网格单元在时区多边形中重复出现
我正在尝试生成一个数据集,将H3分辨率为6 的网格单元映射到时区,以便通过H3到 H3的连接更快速地为一个地理空间/时间数据集生成本地日期时间条目,而不是进行地理空间连接(例如,contains)。我使用Apache Spark和 Sedona来完成这项工作,并使用来自 这里 的timezones-with-oceans-now.geojson.zip数据集。到目前为止,我发现有超过40,000个 H3分辨率为6 的单元格在两个时区中重复(没有一个在三个时区中重复)。以下是我的代码:
import pyspark.sql.functions as sql_functions
from sedona.spark.sql import st_functions as stf
timezones = (
sedona.read.format("geojson")
.load("s3a://my_bucket/timezones/*.json")
.option("multiline", "true")
.selectExpr("explode(features) as features")
.select("features.*")
.withColumn("timezone_id", sql_functions.expr("properties['tzid']"))
.drop("properties", "type")
.repartition(200)
.select(
"timezone_id",
sql_functions.explode(stf.ST_H3CellIDs("geometry", 6, False)).alias("h3_res6")
)
)
重复项在以下查询中显示:
(
timezones
.groupBy("h3_res6")
.agg(
sql_functions.collect_set("timezone_id").alias("timezone_ids"),
sql_functions.count("*").alias("count")
)
.filter(sql_functions.col("count") > 1)
.groupBy("timezone_ids")
.agg(
sql_functions.array_size(
sql_functions.collect_set("h3_res6")
).alias("num_h3_res6")
)
.orderBy(sql_functions.col("num_h3_res6").desc())
.show(25, truncate=False)
)
+----------------------------------------+-----------+
|timezone_ids |num_h3_res6|
+----------------------------------------+-----------+
|[Asia/Manila, Asia/Dhaka] |40001 |
|[Europe/Moscow, Asia/Dubai] |352 |
|[Asia/Gaza, Asia/Jerusalem] |116 |
|[America/Los_Angeles, America/Anchorage]|67 |
|[America/New_York, America/Halifax] |14 |
|[Asia/Kolkata, Asia/Kathmandu] |14 |
|[Asia/Dhaka, Asia/Karachi] |9 |
|[Asia/Manila, Asia/Tokyo] |8 |
|[Africa/Lagos, Europe/Paris] |5 |
|[America/Anchorage, America/Phoenix] |4 |
|[Asia/Jakarta, Asia/Yangon] |4 |
|[Europe/Moscow, Asia/Karachi] |3 |
|[Asia/Kolkata, Asia/Dhaka] |2 |
|[Africa/Casablanca, Europe/Paris] |2 |
|[Africa/Johannesburg, Europe/Moscow] |2 |
|[Asia/Jakarta, Asia/Manila] |1 |
|[Asia/Tokyo, Australia/Brisbane] |1 |
|[America/Los_Angeles, Pacific/Gambier] |1 |
|[Europe/Athens, Africa/Johannesburg] |1 |
|[America/Denver, America/Phoenix] |1 |
|[Pacific/Honolulu, Pacific/Pago_Pago] |1 |
+----------------------------------------+-----------+
我以为使用 fullCover=False 意味着使用H3单元格质心来确定该单元格被分配到哪个多边形。如果确实如此(如有误请纠正我),那么有超过40,000个分辨率为6 的H3单元格的质心恰好位于两个时区之间的边界线上。我猜测另一种可能性是某些时区有重叠的多边形,这会很奇怪。
我的问题是:是否有其他人也遇到过这个问题?这是一个常见/已知的问题吗?如果是,最好的处理方法是什么?我可以通过对每个H3单元格取最小的 timezone_id 来进行确定性去重,但这似乎有些任意。
解决方案
如果你需要一个质心对应一个时区,那么对于这个有歧义的单元格你可能需要创建一个自定义质心。由于这是固定质心,在连接时会对你有帮助。
对于所有这些有歧义的H3单元格,使用时区形状文件和H3单元格多边形来获取交集,作为一个闭合多边形,然后使用Python的 shapely库得到一个自定义的质心。
from shapely.geometry import Polygon
import h3
# Define two overlapping polygons
timezone_poly = Timezone shape polygon
H3_poly = H3 Cell 6 polygon
# Get the intersection geometry
intersection_poly = timezone_poly.intersection(H3_poly)
#For each custom polygon create a another lower level of H3 Cell eg: 2 level. Get a list of all cell level2 ids which has only one time zone.
h3_lower_cells = h3.polygon_to_cells(h3.LatLngPoly(intersection_poly), 2)
#Create a pyspark python udf function which based lat/log provide you a centroid either based H3 cell 6 for a custom centroid we calculated.
# mapping lat/long to H3cell6 centroid or custom centroid. reduce the lookup of poly contains to fewer records.
function map_centroid(lat, long, H3cell6, H3cell2):
ambiguous_cells = set(of h3cell6 ids with multiple timezone)
map_of_h3cell2_centroid = dictionary of mapping
cell_timezone_poly = dictionary of [h3cell6, list of timezone and intersection poly]
centroid = h3.latlng_to_cell(lat, long, 6)
if H3cell6 in ambiguous_cells:
if H3cell2 in map_of_h3cell2_centroid:
centroid = map_of_h3cell2_centroid[H3cell2]
else:
// use the intersection poly of check which timezone poly does it matches.
centroid = of the intersection poly.
return centroid;
这只是一个伪代码,用来给你一个思路,请使用这个PySpark转换。若这个方案对你有帮助,请告诉我是否奏效。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。