Wykreślanie punktów na mapach w R (np. Z ggplot2) - jak przesuwać punkty w bok, zaznaczać oryginalne pozycje, łączyć punkty w pobliżu…?

12

Mam bazę danych zawierającą języki, ich długości i szerokości geograficzne oraz wartość cechy (albo kategoria 1, kategoria 2 lub obie - na wykresie są one oznaczone odpowiednio czerwonym, niebieskim i zielonym). Mogą występować maksymalnie trzy punkty na język i oczywiście dwa punkty językowe mogą znajdować się bardzo blisko siebie.

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

Używam pakietu R ggplot2 (to ten, który znam najbardziej, więc chętnie bym go nadal używał - ale mile widziane są również inne rozwiązania). Oto kadr z poprzedniej próby (kod: patrz poniżej 1 ):

Kadrowanie z poprzedniej próby

W każdym punkcie chciałbym, aby (szorstka) pozycja - a także wartość - była nadal widoczna. (Jeśli istnieje wiele punktów dla jednego języka, można je łączyć).

Czy istnieje sposób na ...

  • ... aby przesunąć punkty na bok tylko na tyle, aby nie było przerysowania (mniej losowo niż, powiedzmy, przy użyciu geom_jitter - na przykład istnieje wiele tego rodzaju unikania w pakiecie ochrony pszczół )?
  • ... i / lub mieć jakąś „linię” wskazującą pierwotne położenie punktu, gdyby musiał zostać przesunięty?
  • ... lub połączyć punkty poboczne w taki sposób, aby były one nadal wyraźne (prawdopodobnie istnieje tam technika działania, która wykorzystuje binowanie, tj. stat_bin * lub coś z podobnym efektem)?
  • ... lub stworzyć „interaktywną fabułę”, taką jak te widoczne na stronach internetowych, które nadal mogą być zawarte w pliku pdf (myślę też o możliwościach pakietów takich jak animacja i błyszczące tutaj)? Na przykład wygląda to tak na wals.info :

    wals

Z poprzedniego postu wiem, że pakiet directlabels może przenosić etykiety, ale nie znalazłem sposobu, aby przenieść punkty również.

Poproś o wyjaśnienia!

Uwaga: zdaję sobie sprawę z tego, że pojawiło się wiele pytań dotyczących nadmiernego plotkowania, ale te, na które spojrzałem, wydawały się mieć inny (tj. Statystyczny) cel (nie twierdzę, że wszystko przeczytałem , więc „ d oczywiście chętnie zaakceptuje link). Spróbuję wymienić te posty, które znam i które mogą być odpowiednie (- z tego, co przeczytałem, żaden z nich nie odpowiada dokładnie na moje pytanie).


1 Poniższe wiersze kodu utworzyły kadr z góry.

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
źródło
Czy jest coś, co mogę poprawić, aby pytanie było łatwiejsze do zrozumienia i odpowiedzi? Daj mi znać, jeśli masz jakieś pomysły!
maj
1
Nie jest to pytanie, z którym mam odpowiednie umiejętności, ale poradziłem sobie, aby na niektórych listach było nieco wyżej. Jeśli nie otrzymujesz żadnych komentarzy, które pomogłyby go ulepszyć, a w każdym razie zalecam częste przeglądanie go / przeglądanie, biorąc pod uwagę porady oferowane na stronie meta.gis.stackexchange.com/a/3353
PolyGeo
Myślę, że możesz chcieć skorzystać z funkcji grafu kierowanego siłą. Nie jestem pewien, jak to zrobić i utrzymać niektóre punkty w zakotwiczeniu, ale myślę o tym, aby zidentyfikować wszystkie klastry (przez jakąś funkcję grupowania bliskości) i użyć środka ciężkości klastra jako kotwicy i pozwolić jej członkom się unosić (a nie wykreślanie samego centroidu - wystarczy użyć go do zakotwiczenia połączonych wierzchołków na jego małym wykresie). I oczywiście, jeśli jakieś klastry mają tylko jednego członka, to również powinny być zakotwiczone w ich lokalizacji.
aaryno
Nie poszedłem na bok w „... znowu wydaje się dotyczyć tylko wykresów rozrzutu”, ponieważ jest to wykres rozrzutu.
whuber
Przyznaję, że musiałem użyć niewłaściwego terminu - to, co chciałem powiedzieć przez wykres rozrzutu, było typowym statystycznym wykresem rozrzutu, w którym pozycja jest generalnie mniej ważna niż w rodzaju wykresu, który tu mamy (= mapa - jeśli punkty są tu przenoszone, to oczywiste natychmiast).
maj

Odpowiedzi:

2

Do tej pory znalazłem tylko jedno całkiem przyzwoite obejście: pakiet packcircles R mógł być zaprojektowany do innego celu, ale robi dobrą robotę, odsuwając punkty od siebie (patrz także odpowiedni post na blogu ). Może nie rozumiem wszystkich wewnętrznych działań tego pakietu, ale na szczęście, jak się okaże, przykładowy plik ze strony internetowej może być używany prawie bezpośrednio - wystarczy zmienić nazwy zmiennych, odległość między okręgami (lub punktami , w zależności od używanych funkcji) i „granic” wykresu (tj. 180 °).

(Ostatecznie wszystko sprowadza się do circleLayout()funkcji, która przyjmuje ramkę danych z kolumnami lon, lat i promień (tj. Odległość) oraz dwa 2-numeryczne wektory xlim / ylim - zwraca ramkę danych z poprawionymi pozycjami punktów.)

„Fabuła”, która jest zwykle tworzona przez packcircles - widać, że już tu działa. mapa

  • porównaj tę mapę „po” z fragmentem mapy „przed” z pytania
maj
źródło
0

Może coś takiego?

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
Nie mam
źródło
Widzę. Próbowałeś odtworzyć „linie do pierwotnej pozycji” ze zrzutu ekranu z wals.info, prawda? To chyba początek. Ale jeśli zobaczę to poprawnie, nie rozwiąże to większej części mojego problemu (np. Punkty nadal się pokrywają).
maj
Resztą powinna być manipulacja ramką danych. Pętla if / for może regulować odstępy - oświadczenie w niej może również powiedzieć, że jeśli odstęp między punktami jest mniejszy niż x, zaznacz je jako takie, a znacznik może być użyty do konkatenacji punktów
mam nadzieję, że ktoś lub ty może naprawić moje brzydkie pętle. Powodzenia.
@InNoam: W rzeczywistości jestem otwarty na wskazówki, jak może działać ta „manipulacja ramkami danych”.
maj