Punktüberzeichnung auf Karten in R (zB mit ggplot2) - wie kann man Punkte zur Seite schieben, ursprüngliche Positionen markieren, Nahpunkte kombinieren ...?

12

Ich habe eine Datenbank mit Sprachen, deren Längen- und Breitengraden und einem Merkmalswert (entweder Kategorie 1, Kategorie 2 oder beides - im Plot sind diese rot, blau und grün markiert). Es kann bis zu drei Punkte pro Sprache geben und natürlich können zwei Sprachpunkte sehr nahe beieinander liegen.

    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
...

Ich verwende das R-Paket ggplot2 (das ist das, mit dem ich am vertrautesten bin, daher würde ich es gerne weiter verwenden - aber andere Lösungen sind auch willkommen). Hier ist eine Ernte aus einem früheren Versuch (Code: siehe unten 1 ):

Ausschnitt aus dem vorherigen Versuch

Für jeden Punkt möchte ich, dass die (raue) Position - sowie der Wert - noch sichtbar sind. (Wenn es für eine Sprache mehrere Punkte gibt, können diese kombiniert werden.)

Gibt es auch einen Weg ...

  • ... um Punkte nur so weit zur Seite zu bewegen, dass es zu keinem Überzeichnen kommt (weniger zufällig als zum Beispiel mit geom_jitter - im Bienenwarm- Paket gibt es zum Beispiel viele solcher Ausweichmanöver )?
  • ... und / oder um eine Art "Linie" zu haben, die auf die ursprüngliche Position eines Punktes zeigt, wenn dieser verschoben werden musste?
  • ... oder um nahegelegene Punkte so zu kombinieren, dass sie immer noch klar sind (es gibt wahrscheinlich eine Arbeitstechnik, die das Binning verwendet, dh stat_bin * oder etwas mit einem ähnlichen Effekt)?
  • ... oder um ein "interaktives Diagramm" zu erstellen, wie es auf Websites zu sehen ist, das noch in ein PDF eingefügt werden kann (ich denke auch an die Fähigkeiten von Paketen wie Animation und Glänzen hier)? Auf wals.info sieht es zum Beispiel so aus :

    wals

Aus einem früheren Beitrag hier weiß ich, dass mit dem DirectLabels- Paket Beschriftungen verschoben werden können, aber ich habe keine Möglichkeit gefunden, die Punkte ebenfalls zu verschieben.

Fühlen Sie sich frei, um Klarstellung zu bitten!

Hinweis: Ich bin mir bewusst, dass es eine Reihe von Fragen zum Überzeichnen gab, aber diejenigen, die ich untersucht habe, schienen einen anderen (dh statistischen) Zweck zu haben (ich behaupte nicht, alles gelesen zu haben , also habe ich ' würde mich natürlich auch über einen Link freuen). Ich werde versuchen, die Posts aufzulisten, die ich kenne und die möglicherweise relevant sind (- nach dem, was ich gelesen habe, beantwortet keine dieser Posts meine Frage genau).


1 Die folgenden Codezeilen haben den Zuschnitt von oben erstellt.

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
Maj
quelle
Gibt es etwas, das ich verbessern kann, um die Frage verständlicher zu machen und zu beantworten? Bitte lassen Sie mich wissen, wenn Sie irgendwelche Ideen haben!
maj
1
Dies ist keine Frage, bei der ich relevante Fähigkeiten habe, aber ich habe sie verbessert, damit sie in einigen Listen etwas höher erscheint. Wenn Sie keine Kommentare erhalten, die zu einer Verbesserung beitragen, und auf jeden Fall empfehle ich, diese in regelmäßigen Abständen zu überprüfen / zu überarbeiten, und dabei den Rat zu beachten, der unter meta.gis.stackexchange.com/a/3353
PolyGeo
Ich denke, Sie möchten möglicherweise eine erzwungene Diagrammfunktion verwenden. Ich bin mir nicht sicher, wie ich es machen soll, um einige Punkte zu verankern, aber ich denke, ich identifiziere alle Cluster (durch eine Näherungsgruppierungsfunktion) und verwende den Cluster-Schwerpunkt als Anker und lasse seine Mitglieder schweben (und nicht Zeichnen Sie den Schwerpunkt selbst - verwenden Sie ihn nur, um die verbundenen Scheitelpunkte in seinem kleinen Diagramm zu verankern. Und natürlich sollten Cluster, die nur ein Mitglied haben, auch an ihrem Standort verankert sein.
Aaryno
Ich folgte nicht der beiseite „... wieder nur auf Scatterplots anzuwenden scheint“ , denn dies ist ein Streudiagramm.
Whuber
Ich muss zugeben, dass ich einen falschen Begriff verwendet habe - was ich mit Streudiagramm sagen wollte, war das typische statistische Streudiagramm, bei dem die Position im Allgemeinen weniger wichtig ist als bei der Art des Diagramms, das wir hier haben (= eine Karte - wenn Punkte hierher verschoben werden, ist dies offensichtlich sofort).
maj

Antworten:

2

Bisher habe ich nur eine recht anständige Problemumgehung gefunden: Das Paket packcircles R wurde möglicherweise für einen anderen Zweck entwickelt, aber es leistet gute Arbeit, indem es die Punkte voneinander wegdrückt (siehe auch den entsprechenden Blog-Beitrag ). Ich verstehe möglicherweise nicht alle Funktionen dieses Pakets, aber zum Glück kann die Beispieldatei von der Website, wie Sie feststellen werden, fast direkt verwendet werden - alles, was geändert werden muss, sind die Variablennamen, der Abstand zwischen Kreisen (oder Punkten) (abhängig von den verwendeten Funktionen) und den "Grenzen" des Graphen (dh 180 °).

(Am Ende kommt es auf die circleLayout()Funktion an, die einen Datenrahmen mit Lon-, Lat- und Radiusspalten und zwei 2-numerischen xlim / ylim-Vektoren verwendet - sie gibt den Datenrahmen mit verbesserten Punktpositionen zurück.)

"Plot", das normalerweise von Packkreisen erstellt wird - hier funktioniert es bereits. Karte

  • Bitte vergleichen Sie diese Nachher-Map mit dem Vorher-Map-Snippet aus der Frage
Maj
quelle
0

So etwas vielleicht?

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
lnNoam
quelle
Aha. Sie haben versucht, die "Zeilen an die ursprüngliche Position" aus dem Screenshot von wals.info zu replizieren, nicht wahr? Es ist ein Anfang, denke ich. Wenn ich das aber richtig sehe, löst es den größten Teil meines Problems nicht (zB überschneiden sich die Punkte immer noch).
maj
Der Rest sollte Datenrahmenmanipulation sein. Eine if / for-Schleife kann den Abstand regeln - eine Aussage darin kann auch besagen, dass, wenn der Abstand zwischen zu Punkten kleiner als x ist, diese als solche markiert werden und dieser Marker zum Verketten der Punkte verwendet werden kann
hoffentlich kann jemand oder Sie meine hässliche Schleife reparieren. Viel Glück.
@InNoam: Tatsächlich bin ich offen für Hinweise, wie diese "Datenrahmenmanipulation" funktionieren könnte.
maj