Estou tendo um problema irritante para o qual estou tentando encontrar uma solução automatizada. A versão abreviada é que eu tenho um shapefile e uma tabela de dados criados para regiões dentro de países. A tabela de dados criada NÃO possui nenhum tipo de código GIDs / administrador padronizado para corresponder aos arquivos de forma, e os nomes das regiões também não são correspondências exatas. Vamos olhar mais de perto; aqui está o meu quadro de dados fictício + shapefile.
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)
Então, o que tenho é uma tabela com IDs aparentemente aleatórios, nomes de regiões e um valor a ser plotado com um mapa de coropletas. Se parece com isso:
> 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
Observando os atributos shapefile de interesse, temos o seguinte:
> 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
incluiria algum tipo de ID de administrador correspondente para ingressar no shapefile. Quem criou os dados que estou usando não seguiu essas convenções, infelizmente. Como alternativa, seria ótimo corresponder os nomes das regiões ... mas, como você pode ver, há pequenas variações em cada nome.
Fazer a correspondência manualmente é sempre uma solução de backup, mas quem quer dedicar algum tempo para fazer isso? ;) Mas, realmente, apesar da preguiça, o projeto em que estou trabalhando mapeará dezenas e dezenas de países diferentes, por isso estou procurando uma solução automatizada que possa fazer tudo sem ter que fazer nada manualmente. Isso é possível? De alguma forma, posso combinar esses nomes de quase região com os shapefiles?
Nota: Estou procurando grepl
por correspondências parciais de strings por esta postagem , mas não tenho certeza se essa é uma solução em potencial, pois precisarei desenhar os nomes das colunas em vez de inserir manualmente o nome de cada região.
EDIT: Quando eu correspondo os IDs manualmente, o que eu fiz foi criar uma nova coluna no meu quadro de dados e adicionar os termos correspondentes exatamente do shapefile. Infelizmente, devido às peculiaridades dos dados, a ordem dos nomes também não corresponde, portanto, isso ainda requer alguma entrada manual. Estou esperando por algum tipo de solução completamente automatizada (se é que é possível).
fonte
Respostas:
Eu iria para o
stringdist
pacote que implementou muitos algoritmos para calcular a similaridade parcial (distância) de strings, incluindoJaro-winkler
. Aqui está uma solução rápida para você:produz:
Você pode jogar com o parâmetro maxDist do método amatch. Embora 3 funcione melhor com seus dados de amostra!
fonte
arm.data
paraarm@data
e funcionaria perfeitamente.arm@data
, que iria criar uma grande confusão (registros não corresponde suas geometrias correctas)Quero acrescentar alguns detalhes à resposta de Farid Cher, pois esse é um problema muito comum. Usando
amatch
pode fazer maravilhas, mas com estesSpatial
objetos que você deve não usarbase::merge
e não acessar o@data
slot. Isso inevitavelmente levaria a uma bagunça terrível (base::merge
muda a ordem dos registros e eles não combinariam mais com as geometrias).Em vez disso, use o
sp::merge
método, usando oSpatialPolygonsDataFrame
primeiro argumento emmerge
. Observe também o possível problema de ter registros duplicados. E adicionei dados para que o exemplo seja independente e reproduzível.este
falha com a mensagem
Porque existem dois registros para "Aragatsotn" em
df
. Você poderia fazerMas normalmente a abordagem sensata é usar algo como
Agora, a mesclagem não funciona bem nesse caso, porque os nomes não correspondem. Então você pode usar
Quase lá, mas "Yerevan City" não combina com "Erevan". Nesse caso, você pode aumentar
maxDist
Mas aumentar
maxDist
nem sempre funcionará ou fornecerá correspondências erradas, pois os nomes das variantes podem ser muito distintos. Portanto, em muitos casos, você fará algumas substituições manuais, como:Nos dois casos seguidos por
Em qualquer caso, você desejará verificar se
sum(table(i) > 1) == 0
; emboramerge
deva falhar mesmo assim, se houver correspondências duplicadas.fonte
merge
. Agregada espacial é útil para casos diferentes (se, neste exemplo,NAME_1
tiveram duplicatas.)