5 votos

¿Unir por atributos "casi" idénticos con QGIS?

Así que tengo dos shapefiles punto - su tabla de atributos consisten en nombres, lat, lon, y otros.

Me gustaría unir los atributos del shapefile 1 al shapefile 2. Una unión normal entre los nombres haría el trabajo.

El problema es que los dos conjuntos de datos tienen ligeras diferencias en el campo "nombre", así como en la lat/lon. Por ejemplo, si tengo un punto en La Haya, Shapefile 1 lo llamará "Den Hague", mientras que Shapefile 2 lo llamará "T. Hague'. Además, espacialmente no son idénticos (no se solapan), por lo que la ubicación entre ambos diferiría en unos pocos kms a pesar de ser el mismo punto. Tengo más de 7000 puntos, lo que dificulta las correcciones manuales. Cuando algunos puntos son realmente correctos.

¿Existe alguna forma de hacer una correspondencia que tenga en cuenta el ~80% de similitud en los nombres?

Estoy utilizando QGIS.

9voto

ghotan Puntos 29

Permítame responder a su Is there a way to do a matching which takes into account ~80% of similarity in the names? .

QGIS dispone de una función levenshtein() que calcula Levenshtein edit distance . Está bajo Fuzzy matching y encontrará una descripción detallada de esta función en el área de ayuda.

En resumen, podemos cuantificar cuánto difieren dos cadenas de entrada.

enter image description here

Arriba hay un ejemplo que muestra el posible uso ---

  • "Led" (distancia de edición de Levenshtein) se calculó mediante levenshtein('Den Hague', "city") cuál es la diferencia entre un texto 'Den Hague' y cada uno de los nombres del "city" campo.
  • Si "city" es Den Hague son idénticos. Por lo tanto "Led" devuelve 0 . Y Rotterdam , completamente diferente, vuelve 9 .
  • Tenga en cuenta que distingue entre mayúsculas y minúsculas (véase el punto 7).

TLNR;

El ejemplo anterior muestra un "YesNo" que determina si dos cadenas coinciden (más del 80%), mediante una expresión a continuación:

CASE WHEN
(length("city") -  levenshtein('Den Hague', "city"))/length('Den Hague') > 0.8
THEN 'Y'
ELSE 'N'
END

Soy consciente de que su objetivo final es utilizar este cotejo en siguientes Join operación. Para ello tendrá que modificar fijo 'Den Hague' a un enlace a su otra capa. Por favor, añada más información como el nombre de la capa y los nombres de los campos si necesita más ayuda. De todos modos, espero que esto ayude.

3voto

Raoul Puntos 1113

Con QGIS 3.8, ahora puede utilizar la función agregada para encontrar la coincidencia más cercana a su nombre utilizando la distancia levenshtein.

Suponiendo que la capa objetivo sea layer2 y el nombre del campo es name añada un nuevo campo fuzzymatch en layer1 con la siguiente expresión y hacer un join basado en ese campo.

array_first(aggregate(
layer:= 'layer2',
aggregate:='array_agg',
expression:=name,
filter:=levenshtein(name, attribute(, 'name')) <= 2,
order_by:=levenshtein(name, attribute(, 'name'))
))

He descrito los pasos en https://spatialthoughts.com/2019/09/26/fuzzy-table-joins-in-qgis/

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X