es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo puedo encontrar el país utilizando información de latitud y longitud usando Pyspark & shapely.

Tengo dos tablas, una presenta todos los países y sus polígonos y multipolígonos respectivos. La otra presenta puntos de latitud y longitud (dist_base).

Mi objetivo es “unir” mis datos de puntos a sus respectivos países. Estoy usando Pyspark y no puedo usar geopandas, por lo que estoy utilizando shapely, pero la forma en que lo estoy implementando es muy lenta.

¿Tiene algún consejo sobre el uso de shapely? La idea sería verificar en qué polígono está ubicado mi punto.

Lo que intenté es verificar polígono por polígono (almacenado en geodata_countries_geo), si el punto está dentro, si es así, recuperar el código ISO3 asociado (almacenado en un diccionario geodata_countries_geo_dict).

import shapely.wkt as wkt

def check<em>nearest</em>country(lat, lon):
    point = Point(lon, lat)
    for geometry in geodata<em>countries</em>geo:
        polygon = wkt.loads(geometry[0])
        if polygon.contains(point):
            return str(geodata<em>countries</em>geo_dict.get(str(geometry[0])))

<h1>registro udf</h1>

check<em>nearest</em>country<em>udf = f.udf(lambda x,y: str(check</em>nearest_country(x,y)), StringType())

<h1>aplicar</h1>

dist<em>base = dist</em>base.withColumn('Country<em>Base</em>ISO3', check<em>nearest</em>country_udf(f.col("lat"),f.col("lon")))

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Una forma de optimizar tu implementación actual es usar la Indexación Espacial. Shapely proporciona una implementación de la estructura de indexación R-tree llamada shapely.strtree. La idea es usar esta estructura de datos para encontrar rápidamente qué polígonos contienen el punto dado. Aquí hay un ejemplo de cómo puedes modificar tu función para usar el R-tree:

    from shapely.geometry import Point
    from shapely.strtree import STRtree
    
    # Convertir geodata_countries_geo en objetos shapely Polygon
    geodata_countries_poly = [wkt.loads(geometry[0]) for geometry in geodata_countries_geo]
    
    # Construir índice R-tree
    geodata_countries_idx = STRtree(geodata_countries_poly)
    
    def check_nearest_country(lat, lon):
        point = Point(lon, lat)
        # Encontrar todos los polígonos que intersectan con el punto utilizando el R-tree
        candidate_polygons = geodata_countries_idx.query(point)
        for polygon in candidate_polygons:
            if polygon.contains(point):
                return str(geodata_countries_geo_dict[str(polygon)])
        return None
    
    # Registrar udf
    check_nearest_country_udf = f.udf(lambda x, y: check_nearest_country(x, y), StringType())
    
    # Aplicar
    dist_base = dist_base.withColumn('Country_Base_ISO3', check_nearest_country_udf(f.col("lat"), f.col("lon")))
    

    Esta implementación debería ser más rápida ya que usa un R-tree para filtrar polígonos que no intersectan con el punto. Ten en cuenta que estamos usando geodata_countries_poly en lugar de geodata_countries_geo porque STRtree requiere objetos Shapely como entrada, no cadenas WKT. Además, devolver None en lugar de una cadena si no se encuentra ningún polígono coincidente es una cuestión de preferencia personal.

Comments are closed.