2013-08-08 6 views
16

Nicht, dass es für meine Frage kritisch ist, aber hier ist mein Diagramm Beispiel, auf dem ich gerne eine Maßstabsleiste hinzufügen würde.Gibt es eine Möglichkeit, eine Maßstabsleiste (für lineare Abstände) zu ggmap hinzuzufügen?

ggmap(get_map(location = "Kinston, NC", zoom = 12, maptype = 'hybrid')) + 
geom_point(x = -77.61198, y = 35.227792, colour = "red", size = 5) + 
geom_point(x = -77.57306, y = 35.30288, colour = "blue", size = 3) + 
geom_point(x = -77.543, y = 35.196, colour = "blue", size = 3) + 
geom_text(x = -77.575, y = 35.297, label = "CRONOS Data") + 
geom_text(x = -77.54, y = 35.19, label = "NOAA") + 
geom_text(x = -77.61, y = 35.22, label = "PP Site") 

NC map

+0

Hallo, schauen Sie sich 'OSM_scale_lookup' und die zugehörigen FAQ-Links –

Antwort

13

Es gibt ein paar Dinge, die Sie tun müssen, damit dies geschieht.

Zunächst ist Ihre Daten in eine data.frame() setzen: Jetzt

sites.data = data.frame(lon = c(-77.61198, -77.57306, -77.543), 
         lat = c(35.227792, 35.30288, 35.196), 
         label = c("PP Site","NOAA", "CRONOS Data"), 
         colour = c("red","blue","blue")) 

wir die Karte für diese Region bekommen kann mit dem gg_map Paket:

require(gg_map) 
map.base <- get_map(location = c(lon = mean(sites.data$lon), 
           lat = mean(sites.data$lat)), 
        zoom = 10) # could also use zoom = "auto" 

Wir werden die Ausmaße, dass brauchen bild:

bb <- attr(map.base,"bb") 

Jetzt fangen wir an, die Skala herauszufinden. Zuerst brauchen wir eine Funktion, die uns den Abstand zwischen zwei Punkten angibt, basierend auf lat/long. Dafür verwenden wir die Haversine Formel, beschrieben von Floris bei Calculate distance in (x, y) between two GPS-Points:

distHaversine <- function(long, lat){ 

    long <- long*pi/180 
    lat <- lat*pi/180 
    dlong = (long[2] - long[1]) 
    dlat = (lat[2] - lat[1]) 

    # Haversine formula: 
    R = 6371; 
    a = sin(dlat/2)*sin(dlat/2) + cos(lat[1])*cos(lat[2])*sin(dlong/2)*sin(dlong/2) 
    c = 2 * atan2(sqrt(a), sqrt(1-a)) 
    d = R * c 
    return(d) # in km 
} 

Der nächste Schritt, um die Punkte zu erarbeiten, die unsere Maßstabsleiste definieren. In diesem Beispiel habe ich etwas in der linken unteren Ecke des Grundstücks, mit dem Begrenzungsrahmen, die wir haben bereits herausgefunden:

sbar <- data.frame(lon.start = c(bb$ll.lon + 0.1*(bb$ur.lon - bb$ll.lon)), 
        lon.end = c(bb$ll.lon + 0.25*(bb$ur.lon - bb$ll.lon)), 
        lat.start = c(bb$ll.lat + 0.1*(bb$ur.lat - bb$ll.lat)), 
        lat.end = c(bb$ll.lat + 0.1*(bb$ur.lat - bb$ll.lat))) 

sbar$distance = distHaversine(long = c(sbar$lon.start,sbar$lon.end), 
           lat = c(sbar$lat.start,sbar$lat.end)) 

Schließlich können wir die Karte mit dem Maßstab ziehen.

ptspermm <- 2.83464567 # need this because geom_text uses mm, and themes use pts. Urgh. 

map.scale <- ggmap(map.base, 
        extent = "normal", 
        maprange = FALSE) %+% sites.data + 
    geom_point(aes(x = lon, 
       y = lat, 
       colour = colour)) + 
    geom_text(aes(x = lon, 
       y = lat, 
       label = label), 
      hjust = 0, 
      vjust = 0.5, 
      size = 8/ptspermm) +  
    geom_segment(data = sbar, 
       aes(x = lon.start, 
        xend = lon.end, 
        y = lat.start, 
        yend = lat.end)) + 
    geom_text(data = sbar, 
      aes(x = (lon.start + lon.end)/2, 
      y = lat.start + 0.025*(bb$ur.lat - bb$ll.lat), 
      label = paste(format(distance, 
           digits = 4, 
           nsmall = 2), 
         'km')), 
      hjust = 0.5, 
      vjust = 0, 
      size = 8/ptspermm) + 
    coord_map(projection="mercator", 
      xlim=c(bb$ll.lon, bb$ur.lon), 
      ylim=c(bb$ll.lat, bb$ur.lat)) 

Dann wir es retten ...

# Fix presentation ---- 
map.out <- map.scale + 
    theme_bw(base_size = 8) + 
    theme(legend.justification=c(1,1), 
     legend.position = c(1,1)) 

ggsave(filename ="map.png", 
     plot = map.out, 
     dpi = 300, 
     width = 4, 
     height = 3, 
     units = c("in")) 

Was Sie so etwas wie dieses gibt:

Map with scale bar

Das Schöne daran ist, dass alle der Plotten verwendet ggplot2(), so Sie können die Dokumentation unter http://ggplot2.org verwenden, um dieses Aussehen wie Sie benötigen.

+0

Dies ist eine sehr hilfreiche Antwort @AndyClifton! – Mikko

+0

versuchen, Ihren Code zu verwenden und bin nicht sicher, ob es einen Fehler gibt somehere? überprüfe dein lat/long Beispiel hier: [link] (http://www.movable-type.co.uk/scripts/latlong.html gibt) gibt mir 12,02 km statt der 13,52 die deine Formel bekommt? – maja

+1

Aktualisiert 30. November 2015, um das Problem zu beheben, dass @maja bemerkt, die von mir verursacht wurde nicht Ausdruck der lat/Lon im Bogenmaß in meiner Distanzberechnung. –

5

Ich habe den Code von @Andy Clifton überarbeitet, um ein genaueres Maß für die Entfernung hinzuzufügen und um zu ermöglichen, dass die Maßstabsleiste eine gewünschte Länge hat, im Gegensatz zur Abhängigkeit von der Positionierung des Balkens.

Andys Code hat mich 99 Prozent der Weg, aber die Haversine Formel in seinem Code verwendet wird nicht mit Ergebnissen aus anderen Quellen validiert, obwohl ich den Fehler nicht finden kann.sind verschiedene

sites.data = data.frame(lon = c(-77.61198, -77.57306, -77.543), 
         lat = c(35.227792, 35.30288, 35.196), 
         label = c("PP Site","NOAA", "CRONOS Data"), 
         colour = c("red","blue","blue")) 
map.base <- get_map(location = c(lon = mean(sites.data$lon), 
            lat = mean(sites.data$lat)), 
         zoom = 10) 
bb <- attr(map.base,"bb") 
sbar <- data.frame(lon.start = c(bb$ll.lon + 0.1*(bb$ur.lon - bb$ll.lon)), 
        lon.end = c(bb$ll.lon + 0.25*(bb$ur.lon - bb$ll.lon)), 
        lat.start = c(bb$ll.lat + 0.1*(bb$ur.lat - bb$ll.lat)), 
        lat.end = c(bb$ll.lat + 0.1*(bb$ur.lat - bb$ll.lat))) 

Die nächsten beiden Schritte:

Zuerst verwenden Sie die distVincentyEllipsoid Funktion aus dem berechnen geosphere Paket

Dieser erste Teil ist für die Vollständigkeit der angezeigten Code nur von Andy Clifton Antwort kopiert die Entfernung noch genauer als die Haversine-Formel:

sbar$distance <- geosphere::distVincentyEllipsoid(c(sbar$lon.start,sbar$lat.start), 
c(sbar$lon.end,sbar$lat.end)) 

Dann korrigieren Sie die Maßstabsleiste Das ist eine Standardlänge - abhängig von der Größe Ihrer Karte. In diesem Beispiel scheint 20km wie eine schöne vernünftige Wahl, das heißt 20.000 Meter:

scalebar.length <- 20 
sbar$lon.end <- sbar$lon.start + 
((sbar$lon.end-sbar$lon.start)/sbar$distance)*scalebar.length*1000 

Wieder Andys Code, hinzugefügt habe ich nur die Pfeile auf die geom_segment, weil ich denke, es ist schöner

ptspermm <- 2.83464567 # need this because geom_text uses mm, and themes use pts. Urgh. 

map.scale <- ggmap(map.base, 
        extent = "normal", 
        maprange = FALSE) %+% sites.data + 
    geom_point(aes(x = lon, 
       y = lat, 
       colour = colour)) + 
    geom_text(aes(x = lon, 
       y = lat, 
       label = label), 
      hjust = 0, 
      vjust = 0.5, 
      size = 8/ptspermm) +  
    geom_segment(data = sbar, 
       aes(x = lon.start, 
        xend = lon.end, 
        y = lat.start, 
        yend = lat.end), 
       arrow=arrow(angle = 90, length = unit(0.1, "cm"), 
          ends = "both", type = "open")) + 
    geom_text(data = sbar, 
      aes(x = (lon.start + lon.end)/2, 
       y = lat.start + 0.025*(bb$ur.lat - bb$ll.lat), 
       label = paste(format(scalebar.length), 
           'km')), 
      hjust = 0.5, 
      vjust = 0, 
      size = 8/ptspermm) + 
    coord_map(projection = "mercator", 
      xlim=c(bb$ll.lon, bb$ur.lon), 
      ylim=c(bb$ll.lat, bb$ur.lat)) 

# Fix presentation ---- 
map.out <- map.scale + 
    theme_bw(base_size = 8) + 
    theme(legend.justification = c(1,1), 
     legend.position = c(1,1)) 

ggsave(filename ="map.png", 
     plot = map.out, 
     dpi = 300, 
     width = 4, 
     height = 3, 
     units = c("in")) 

sieht reworked scale bar example

Verwandte Themen