Tengo un problema molesto para el que intento encontrar una solución automatizada. La versión abreviada es que tengo un archivo de formas y una tabla de datos creados para las regiones dentro de los países. La tabla de datos creada NO tiene ningún tipo de GID / códigos de administrador estandarizados para que coincidan con los archivos de forma, y los nombres de las regiones tampoco son coincidencias exactas. Miremos más de cerca; Aquí está mi marco de datos ficticio + archivo de forma.
library(rgdal)
#load in shapefile
arm <- readOGR("D:/Country-Shapefiles/ARM_adm_shp", layer = "ARM_adm1")
#create dummy data frame
id <- c(100:110)
name <- c("Aragatsotn", "Ararat", "Armavir", "Gaghark'unik'", "Kotayk", "Lorri",
"Shirak", "Syunik'", "Tavush", "Vayots' Dzor", "Yerevan City")
value <- runif(11, 0.0, 1.0)
df <- data.frame(id, name, value)
Entonces, lo que tengo es una tabla con identificaciones aparentemente aleatorias, nombres de regiones y un valor que se trazará con un mapa coroplético. Se ve como esto:
> df
id name value
1 100 Aragatsotn 0.6923852
2 101 Ararat 0.5762024
3 102 Armavir 0.4688358
4 103 Gaghark'unik' 0.4702253
5 104 Kotayk 0.9347992
6 105 Lorri 0.1937813
7 106 Shirak 0.5162604
8 107 Syunik' 0.4332389
9 108 Tavush 0.9889513
10 109 Vayots' Dzor 0.2182024
11 110 Yerevan City 0.5791886
Mirando los atributos de archivo shape de interés, tenemos esto:
> arm@data[c("ID_1", "NAME_1")]
ID_1 NAME_1
0 1 Aragatsotn
1 2 Ararat
2 3 Armavir
3 4 Erevan
4 5 Gegharkunik
5 6 Kotayk
6 7 Lori
7 8 Shirak
8 9 Syunik
9 10 Tavush
10 11 Vayots Dzor
Idealmente, df
incluiría algún tipo de ID de administrador coincidentes para unirse al shapefile. Lamentablemente, quien creó los datos que estoy usando no siguió estas convenciones. Alternativamente, sería genial hacer coincidir los nombres de las regiones en sí ... pero como puede ver, hay ligeras variaciones en cada nombre.
Hacer coincidir a mano siempre es una solución de respaldo, pero ¿quién quiere tomarse el tiempo para hacerlo? ;) Pero en realidad, incluso salvo la pereza, el proyecto en el que estoy trabajando estará mapeando docenas y docenas de países diferentes, así que estoy buscando una solución automatizada que pueda hacer todo sin tener que hacer nada a mano. es posible? ¿Puedo de alguna manera hacer coincidir estos nombres de región casi con los archivos de forma?
Nota al margen: Estoy buscando grepl
coincidencias parciales de cadenas por esta publicación , pero no estoy seguro de si esta es una solución potencial porque tendré que extraer de los nombres de columna en lugar de ingresar cada nombre de región a mano.
EDITAR: cuando emparejo las ID a mano, lo que he hecho es crear una nueva columna en mi marco de datos y agregar los términos de coincidencia exactos del archivo de forma. Desafortunadamente, debido a las peculiaridades de los datos, el orden de los nombres tampoco coincide, por lo que esto aún requiere una entrada manual. Espero algún tipo de solución completamente automatizada (si es posible).
fuente
Respuestas:
Iría por el
stringdist
paquete que ha implementado muchos algoritmos para calcular la similitud parcial (distancia) de las cadenas incluidasJaro-winkler
. Aquí hay una solución rápida para usted:produce:
Puedes jugar con el parámetro maxDist del método amatch. ¡Aunque 3 funciona mejor con sus datos de muestra!
fuente
arm.data
aarm@data
, y que funcionaría bien.arm@data
, eso crearía un gran desastre (los registros no coinciden con sus geometrías correctas)Quiero agregar algunos detalles a la respuesta de Farid Cher ya que este es un problema muy común. Usando
amatch
puede hacer maravillas, pero con estosSpatial
objetos se debe no utilizarbase::merge
y no tener acceso a la@data
ranura. Eso conduciría inevitablemente a un terrible desastre (base::merge
cambia el orden de los registros y ya no coincidirían con las geometrías).En su lugar, use el
sp::merge
método, usando elSpatialPolygonsDataFrame
primer argumento enmerge
. También tenga en cuenta el problema potencial de tener registros duplicados. Y agregué datos para que el ejemplo sea autónomo y reproducible.Esta
falla con el mensaje
Porque hay dos registros para "Aragatsotn" en
df
. Podrías hacerloPero normalmente el enfoque sensato es usar algo como
Ahora, fusionar no funciona bien en este caso porque los nombres no coinciden. Entonces puedes usar
Casi allí, pero "Ciudad de Ereván" no coincidía con "Erevan". En este caso puedes aumentar
maxDist
Pero aumentar
maxDist
no siempre funcionará o dará coincidencias incorrectas porque los nombres de las variantes pueden ser muy distintos. Entonces, en muchos casos, terminará haciendo algunos reemplazos manuales como:En ambos casos seguido de
En cualquier caso, querrá verificar si
sum(table(i) > 1) == 0
; aunquemerge
debería fallar de todos modos si hay coincidencias duplicadas.fuente
merge
. El agregado espacial es útil para diferentes casos (si, en este ejemplo,NAME_1
tenía duplicados)