Python: Quebrar a cadeia de linhas com base na condição


11

Eu tenho um quadro de dados geopandas de um monte de cadeias de linhas que têm alguns dados associados a cada vértice / ponto:

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

Os pontos são convertidos em cadeias de linhas com base no ID e ordenados por Hora.

Eu quero quebrar as cadeias de linhas onde, no ponto em que alguma condição é atendida. Agora é quando a distância entre os pontos é maior que algum valor. No futuro, pode ser que uma função dos campos Dados tenha algum valor. Por exemplo, divida uma cadeia de linhas quando o Speed ​​ultrapassar 5 km / h.

O problema atual é que algumas das faixas são formadas a partir de pontos com IDs duplicados, de modo que a cadeia de linhas salta para frente e para trás por grandes distâncias e eu quero um limite para quebrar essas linhas.

Alguma idéia sobre a maneira correta de estruturar isso ou bibliotecas / métodos que possam ser úteis?

O dataframe possui mais de 150 mil trilhas com muitos pontos por trilha, portanto a eficiência seria boa.

Aqui está um exemplo das faixas 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...     

Aqui está uma amostra dos pontos DF. Existem 18 colunas, incluindo Datetime, Point (Lon, Lat), Speed, Size 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               

EDIT: Tentei ser um pouco mais claro.


Qual é a estrutura do seu GeoDataFrame? Uma cópia gd.head()seria bem-vinda.
gene

Editado para mostrar a cabeça
RedM

Eu usei o GeoPy (geopy.distance.vincenty) no passado para algo semelhante. Eu precisava conectar pontos, mas não os queria conectados se fossem mais longos que o meu limite determinado. Enviei cada par de coordenadas através da função e as conectei apenas se fossem inferiores ao meu limite. geopy.readthedocs.io/en/1.10.0/#geopy.distance.vincenty
JohnR

Qual é a chave primária / condição de classificação para o recurso de ID duplicado: tempo vs. ID ou ID vs. tempo?
huckfinn

Não tenho muita certeza do que você quer dizer. Os pontos são agrupados por ID, depois classificados por hora e, em seguida, pelas posições ordenadas usadas para criar uma sequência de linhas. Às vezes, o ID é duplicado entre os objetos. Exemplo: Existe um carro na cidade A com ID = '123'. Está transmitindo sua posição e tempo. Há também um carro na cidade B com ID = '123' e também está transmitindo suas posições e os horários são intercalados. Uma linha construída a partir desses pontos saltaria entre A e B
RedM

Respostas:


1

Ainda não usei o shapely / geopandas, então só posso fornecer o 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

A função de distância deve ser algo que suas bibliotecas já oferecem, ou você terá que implementá-la você mesmo (o velho Pythagoras o ajudará).

A eficiência pode ser melhorada conforme necessário a partir daí, mas deve ser um bom ponto de partida.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.