J'ai un problème ennuyeux pour lequel j'essaie de trouver une solution automatisée. La version abrégée est que j'ai un fichier de formes et un tableau de données créées pour les régions au sein des pays. La table de données créée n'a AUCUNE sorte de GID / codes d'administration standardisés à faire correspondre aux fichiers de formes, et les noms de région ne sont pas non plus des correspondances exactes. Regardons de plus près; voici mon faux cadre de données + 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)
Donc, ce que j'ai, c'est un tableau avec des identifiants apparemment aléatoires, des noms de régions et une valeur à tracer avec une carte choroplèth. Ressemble à ça:
> 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
En regardant les attributs de fichiers de formes d'intérêt, nous avons ceci:
> 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
Idéalement, il df
faudrait inclure une sorte d'ID administrateur correspondant à joindre au fichier de formes. Celui qui a créé les données que j'utilise n'a malheureusement pas respecté ces conventions. Alternativement, ce serait bien de faire correspondre les noms de région eux-mêmes ... mais comme vous pouvez le voir, il y a de légères variations dans chaque nom.
L'appariement à la main est toujours une solution de sauvegarde, mais qui veut prendre le temps de le faire? ;) Mais vraiment, même en dehors de la paresse, le projet sur lequel je travaille sera de cartographier des dizaines et des dizaines de pays différents, donc je recherche une solution automatisée qui peut tout faire sans rien faire à la main. Est-ce possible? Puis-je d'une manière ou d'une autre faire correspondre ces noms de région-presque aux fichiers de formes?
Sidenote: Je cherche grepl
des correspondances de chaînes partielles dans cet article , mais je ne suis pas sûr que ce soit une solution potentielle car je devrai tirer des noms de colonnes plutôt que d'entrer chaque nom de région à la main.
EDIT: Lorsque je fais correspondre les ID à la main, ce que j'ai fait est de créer une nouvelle colonne dans mon bloc de données et d'ajouter les termes correspondants exacts à partir du fichier de formes. Malheureusement, en raison des particularités des données, l'ordre des noms ne correspond pas non plus, donc cela nécessite encore une saisie manuelle. J'espère une sorte de solution complètement automatisée (si c'est même possible).
Réponses:
J'irais pour un
stringdist
package qui a implémenté de nombreux algorithmes pour calculer la similitude partielle (distance) des chaînes, y comprisJaro-winkler
. Voici une solution rapide pour vous:il génère:
Vous pouvez jouer avec le paramètre maxDist de la méthode amatch. Bien que 3 fonctionne mieux avec vos données d'échantillon!
la source
arm.data
enarm@data
et cela fonctionnerait très bien.arm@data
, cela créerait un gros gâchis (les enregistrements ne correspondant pas à leurs géométries correctes)Je veux ajouter quelques détails à la réponse de Farid Cher car il s'agit d'un problème très courant. L' utilisation
amatch
peut faire des merveilles, mais avec cesSpatial
objets que vous ne devriez pas utiliserbase::merge
et ne pas accéder à la@data
fente. Cela conduirait inévitablement à un terrible gâchis (base::merge
change l'ordre des enregistrements, et ils ne correspondraient plus aux géométries).À la place, utilisez la
sp::merge
méthode en utilisant leSpatialPolygonsDataFrame
comme premier argument dansmerge
. Notez également le problème potentiel d'avoir des enregistrements en double. Et j'ai ajouté des données pour que l'exemple soit autonome et reproductible.Cette
échoue avec le message
Parce qu'il y a deux enregistrements pour "Aragatsotn" dans
df
. Vous pourriez faireMais normalement, l'approche saine consiste à utiliser quelque chose comme
Maintenant, la fusion ne fonctionne pas bien dans ce cas car les noms ne correspondent pas. Vous pouvez donc utiliser
Presque là, mais "Erevan City" ne correspondait pas à "Erevan". Dans ce cas, vous pouvez augmenter
maxDist
Mais augmenter
maxDist
ne fonctionnera pas toujours ou ne donnera pas les bonnes correspondances car les noms de variantes peuvent être très distincts. Donc, dans de nombreux cas, vous finirez par faire des remplacements manuels comme:Dans les deux cas, suivi de
Dans tous les cas, vous voudrez vérifier si
sum(table(i) > 1) == 0
; maismerge
devrait échouer de toute façon s'il y a des correspondances en double.la source
merge
. L'agrégat spatial est utile pour différents cas (si, dans cet exemple, il yNAME_1
avait des doublons.)