Surplotage de points sur des cartes en R (par exemple avec ggplot2) - comment pousser des points sur le côté, marquer des positions originales, combiner des points proches…?


12

J'ai une base de données contenant les langues, leurs longitudes et latitudes et une valeur de caractéristique (catégorie 1, catégorie 2 ou les deux - dans l'intrigue, elles sont marquées respectivement en rouge, bleu et vert). Il peut y avoir jusqu'à trois points par langue et naturellement deux points de langue peuvent être très proches l'un de l'autre.

    name            longitude   latitude    sp_sum
1   Modern Armenian 45          40          both
2   Modern Armenian 45          40          both
3   Modern Armenian 45          40          spatial
4   Dieri           138         -28.1667    both
5   Dieri           138         -28.1667    both
6   Finnish         25.5577     64.7628     non-spatial
7   Crimean Tatar   28.1418     43.8398     spatial
8   Ese Ejja        -67.515     -11.7268    non-spatial
9   Makhuwa         38.8052     -14.8509    non-spatial
...

J'utilise le package R ggplot2 (c'est celui que je connais le mieux, donc je serais heureux de continuer à l'utiliser - mais d'autres solutions sont également les bienvenues). Voici un recadrage d'une tentative précédente (code: voir ci-dessous 1 ):

Recadrage de la tentative précédente

Pour chaque point, j'aimerais que la position (approximative) - ainsi que la valeur - soient toujours visibles. (S'il y a plusieurs points pour une seule langue, ils peuvent être combinés.)

Y a-t-il un moyen non plus ...

  • ... pour déplacer les points sur le côté juste assez pour qu'il n'y ait pas de surplacement (moins au hasard que, par exemple, en utilisant geom_jitter - il y a beaucoup de ce genre d' esquive dans le package beeswarm par exemple)?
  • ... et / ou d'avoir une sorte de "ligne" pointant vers la position d'origine d'un point s'il devait être déplacé?
  • ... ou pour combiner des points proches de manière à ce qu'ils soient toujours clairs (il existe probablement une technique de travail qui utilise le binning, c'est-à-dire stat_bin * ou quelque chose avec un effet similaire)?
  • ... ou pour créer une "intrigue interactive" comme celles vues sur des sites Web qui peuvent encore être inclus dans un pdf (je pense aussi aux capacités de packages comme l' animation et brillant ici)? Par exemple, cela ressemble à wals.info :

    wals

D'après un article précédent ici, je sais que le package directlabels peut déplacer des étiquettes, mais je n'ai pas trouvé de moyen de le faire déplacer également les points.

N'hésitez pas à demander des éclaircissements!

Note: Je sais qu'il ya eu un certain nombre de questions sur overplotting, mais ceux que j'ai regardé dans tous semblaient avoir un autre ( par exemple statistique) but (je ne prétends pas avoir lu tout ce , donc je je serais également heureux d'accepter un lien). Je vais essayer d'énumérer les messages que je connais et qui pourraient bien être pertinents (- d'après ce que j'ai lu, aucun d'eux ne répond exactement à ma question.)


1 Les lignes de code suivantes ont créé le recadrage d'en haut.

library(OpenStreetMap)
library(ggplot2)

data <- read.csv(header = T, sep = ",", dec = ".", quote= "'",
text = "'','name','longitude','latitude','sp_sum'
'1','Modern Armenian',45,40,'both'
'2','Modern Armenian',45,40,'both'
'3','Modern Armenian',45,40,'spatial'
'4','Dieri',138,-28.1667,'both'
'5','Dieri',138,-28.1667,'both'
'6','Finnish',25.5577,64.7628,'non-spatial'
'7','Crimean Tatar',28.1418,43.8398,'spatial'
'8','Sochiapam Chinantec',-96.6079,17.7985,'non-spatial'
'9','Ese Ejja',-67.515,-11.7268,'non-spatial'
'10','Makhuwa',38.8052,-14.8509,'non-spatial'
'11','Mualang',111.077,0.31083,'non-spatial'
'12','Martuthunira',116.607,-20.9294,'non-spatial'
'13','Evenki',108.626,53.85,'both'
'14','Afrikaans',30,-22,'both'
'15','Male (Ethiopia)',36.9892,5.91975,'both'
'16','Manchu',126.557,47.3122,'both'
'17','Dime',36.3329,6.20951,'non-spatial'
'18','Koorete',37.8679,5.80545,'non-spatial'
'19','Wolaytta',37.7537,6.32668,'both'
'20','Dizin',35.5763,6.1405,'both'")

map <- openproj(openmap(c(85, -179.9), c(-60, 179.9), zoom = 2, type = "nps"))
plot <- autoplot(map) + 
  geom_point(data = data, aes(x = longitude, y = latitude),
             color = "white", alpha = 0.8, size = 8) +
  geom_point(data = data, aes(x = longitude, y = latitude, color = sp_sum),
             alpha = 0.3, size = 4)
plot

Y a-t-il quelque chose que je peux améliorer pour rendre la question plus facile à comprendre et à répondre? Veuillez me faire savoir si vous avez des idées!
maj

1
Ce n'est pas une question pour laquelle j'ai des compétences pertinentes, mais je l'ai votée pour la faire apparaître un peu plus haut dans certaines listes. Si vous n'obtenez aucun commentaire permettant de l'améliorer, et en tout état de cause, je vous recommande de le réviser / le réviser à intervalles réguliers en tenant compte des conseils proposés sur meta.gis.stackexchange.com/a/3353
PolyGeo

Je pense que vous voudrez peut-être utiliser une fonctionnalité de graphique forcé. Je ne sais pas comment le faire et garder certains points ancrés, mais ce que je pense, c'est identifier tous les clusters (par une fonction de regroupement de proximité) et utiliser le centre de gravité du cluster comme une ancre et laisser ses membres flotter (et non traçant le centre de gravité lui-même - en l'utilisant simplement pour ancrer les sommets connectés dans son petit graphique). Et bien sûr, si des clusters n'ont qu'un seul membre, ceux-ci doivent également être ancrés à leur emplacement.
aaryno

Je n'ai pas suivi le côté à "... semble encore s'appliquer uniquement aux nuages ​​de points", car il s'agit d' un nuage de points.
whuber

J'avoue que j'ai dû utiliser un mauvais terme - ce que je voulais dire par nuage de points était le nuage de points statistique typique où la position est généralement moins importante que dans le type de graphique que nous avons ici (= une carte - si des points sont déplacés ici, c'est évident immédiatement).
maj

Réponses:


2

Jusqu'à présent, je n'ai trouvé qu'une solution de contournement assez décente: le package packcircles R a peut-être été conçu dans un autre but, mais il fait un bon travail en éloignant les points les uns des autres (voir également le billet de blog correspondant ). Je ne comprends peut-être pas tout le fonctionnement interne de ce package, mais heureusement, comme vous le trouverez, le fichier d'exemple du site Web peut être utilisé presque directement - tout ce qu'il faut changer sont les noms des variables, la distance entre les cercles (ou points , selon les fonctions que vous utilisez) et les "limites" du graphique (ie 180 °).

(En fin de compte, tout se résume à la circleLayout()fonction, qui prend une trame de données avec des colonnes lon, lat et radius (c.-à-d. Distance) et deux vecteurs xlim / ylim à 2 chiffres - elle renvoie la trame de données avec des positions de points améliorées.)

"Plot" qui est généralement créé par packcircles - vous pouvez déjà le voir fonctionner ici. carte

  • veuillez comparer cette carte «après» avec l'extrait de carte «avant» de la question

0

Quelque chose comme ça, peut-être?

data$spacing_x = 5
data$spacing_y = 5

for(i in 2:nrow(data)) {
  if( abs(data$latitude[i]-data$latitude[i+1]) < 2 ) {
    data$spacing_y[i] = data$spacing_y + 6 +jitter(data$spacing_y,8)
    data$spacing_y[i+1] = data$spacing_y + 6 + jitter(data$spacing_y,8)
  }
}

for(i in 2:nrow(data)) {
     if( abs(data$longitude[i]-data$longitude[i+1]) < 2 ) {
      data$spacing_x[i] = data$spacing_x + jitter(data$spacing_x,4)
      data$spacing_x[i+1] = data$spacing_x +jitter(data$spacing_x,4)
     }
}

for(i in 2:nrow(data)) {
  if( abs(data$spacing_y[i]-data$spacing_y[i+1]) < 1.5 ) {
    data$spacing_y[i] = data$spacing_y + 2 
    data$spacing_y[i+1] = data$spacing_y + 2
  }
}

for(i in 2:nrow(data)) {
  if( abs(data$spacing_x[i]-data$spacing_x[i+1]) < 1.5 ) {
    data$spacing_x[i] = data$spacing_x + 2 
    data$spacing_x[i+1] = data$spacing_x + 2
  }
}


plot = autoplot(map) + 
  geom_segment(data = data
               , mapping=aes(x=longitude
                             , y=latitude
                             , xend=longitude + spacing_x
                             , yend=latitude + spacing_y)
               , size=0.5, color="black"
               , alpha = 0.9) +
  geom_point(data = data
             , aes(x = longitude+spacing_x
                  , y = latitude+spacing_y)
             , color = "white"
             , alpha = 0.8, size = 8) +
  geom_point(data = data
             , aes(x = longitude+spacing_x
                   , y = latitude+spacing_y
                   , color = sp_sum)
             , alpha = 0.3, size = 4)
  xlab("") +
  ylab("")
plot

Je vois. Vous avez essayé de reproduire les "lignes à la position d'origine" de la capture d'écran de wals.info, n'est-ce pas? C'est un début, je suppose. Mais si je vois cela correctement, cela ne résoudra pas la majeure partie de mon problème (par exemple, les points se chevauchent toujours).
maj

Le reste devrait être une manipulation de trame de données. Une boucle if / for peut régir l'espacement - une déclaration y figurant peut également dire que si l'espacement entre les points est inférieur à x, marquez-les comme tels et ce marqueur peut être utilisé pour concaténer les points

j'espère que quelqu'un, ou vous, peut réparer mon laid pour les boucles. Bonne chance.

@InNoam: En fait, je suis ouvert à des conseils sur la façon dont cette «manipulation de trame de données» pourrait fonctionner.
maj
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.