Python: romper la cadena lineal según la condición


11

Tengo un marco de datos geopandas de un grupo de cadenas de líneas que tienen algunos datos asociados con cada vértice / punto:

Point_x = (Lat, Lon, Time, ID, Data1, Data2, Data3)

Los puntos se convierten en cadenas de líneas según la ID y se ordenan por tiempo.

Quiero romper las cadenas lineales en el punto donde se cumple alguna condición. En este momento es cuando la distancia entre los puntos es mayor que algún valor. En el futuro podría ser donde una función de los campos de Datos tenga algún valor. Por ejemplo, divida una cadena lineal cuando Speed ​​cruce 5 km / h.

El problema actual es que algunas de las pistas están formadas por puntos que tienen identificaciones duplicadas, por lo que la cadena de líneas salta hacia adelante y hacia atrás a grandes distancias y quiero un umbral para romper estas líneas.

¿Alguna idea sobre la forma correcta de estructurar esto o las bibliotecas / métodos que podrían ser útiles?

El marco de datos tiene más de 150k pistas con muchos puntos por pista, por lo que la eficiencia sería buena.

Aquí hay un ejemplo de las pistas DF:

ID         geometry                                                  
204235000  LINESTRING (37.62001 -28.99535, 37.62015 -28.9...   
205400000  LINESTRING (3.807816666666666 -18.083181666666...   
207138000  LINESTRING (22.73206 -34.97915833333333, 22.73...   
209016000  LINESTRING (8.447673333333331 -23.522783333333...     

Aquí hay una muestra de los puntos DF. Hay 18 columnas que incluyen Fecha y hora, Punto (Lon, Lat), Velocidad, Tamaño, etc., etc.

Index           Heading   Latitude  Longitude       ID  
20              92.8 -35.946802  13.089695  210725000               
21              93.5 -35.946912  13.091808  210725000               
22              95.4 -35.965520  13.497698  210725000               
23              94.7 -35.965803  13.501898  210725000               
24              94.9 -35.965987  13.504573  210725000               

EDITAR: Intenté ser un poco más claro.


¿Cuál es la estructura de su GeoDataFrame? Una copia de gd.head()sería bienvenida.
gen

Editado para mostrar la cabeza
RedM

He usado GeoPy (geopy.distance.vincenty) en el pasado para algo similar. Necesitaba conectar puntos, pero no quería que se conectaran si eran más largos que mi umbral determinado. Envié cada par de coordenadas a través de la función y las conecté solo si eran inferiores a mi umbral. geopy.readthedocs.io/en/1.10.0/#geopy.distance.vincenty
JohnR

¿Cuál es la clave principal / condición de clasificación para la función de ID duplicada: tiempo vs. ID o ID vs. tiempo?
huckfinn

No estoy muy seguro de lo que quieres decir. Los puntos se agrupan por ID, luego se ordenan por tiempo y luego las posiciones ordenadas que se usan para crear una cadena de línea. La identificación a veces se duplica entre objetos. Ejemplo: hay un automóvil en la ciudad A con ID = '123'. Está transmitiendo su posición y tiempo. También hay un automóvil en la ciudad B con ID = '123' y también está transmitiendo sus posiciones y los tiempos están intercalados. Una línea construida a partir de estos puntos saltaría entre A y B
RedM

Respuestas:


1

Todavía no he usado shapely / geopandas, por lo que solo puedo proporcionar pseudocódigo:

distance_threshold = 50 # Value at which distance to cut off
new_lines = [] # Array to hold the newly created, split lines
new_line_marker = 0 # Let's remember where our new line starts
for linestring in linestrings: # Iterate over all linestrings
  for i, coord in enumerate(linestring.coords[:-1]): # Iterate over all coords of the linestring
    if distance(coord, coords[i+1]) >= distance_threshold: # Check if threshold is met
      # If condition is met, we generate a new linestring,
      # starting from the last split to the current one
      new_lines[] = new LineString(coords[new_line_marker:i])
      new_line_marker = i+1 # remember to reset the marker

La función de distancia debe ser algo que tus libs ya ofrezcan, o tendrás que implementarla tú mismo (el viejo amigo Pitágoras te ayudará).

La eficiencia se puede mejorar según sea necesario a partir de ahí, pero debería ser un buen punto de partida.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.