2013-06-17 26 views
9

tôi đã sản xuất bản đồ này trong ggplot2:Thêm thanh tỷ lệ để ggplot đồ

library(maptools); library(ggplot2) 
data(wrld_simpl) 
world <- fortify(wrld_simpl) 
worldUk <- subset(world, id=="GBR") 
ggplot() + 
geom_path(aes(long, lat, group=group), data=worldUk, color="black", fill=NA) + 
    coord_equal() 

enter image description here

Sử dụng photoshop, tôi đã thêm một thanh tỷ lệ bản đồ. Làm cách nào để thêm thanh tỷ lệ tương tự bằng cách sử dụng ggplot2? Bài đăng này thêm thanh tỷ lệ, nhưng thanh không đề cập đến khoảng cách: scale bar and north arrow on map-ggplot2

+0

Các bạn đã thử nghiệm điều này: http://stackoverflow.com/questions/15486551/scale-bar-and-north-arrow-on-map-ggplot2? – Beasterfield

+0

Có - xem liên kết ở cuối câu hỏi – luciano

+3

Chỉ cần quan sát - bạn muốn rất cẩn thận khi đặt các thanh tỷ lệ trên các ô có phạm vi rộng lớn. Tùy thuộc vào phép chiếu bạn chọn, thanh tỷ lệ chỉ có thể hợp lệ trong một phần của hình ảnh. Vì vậy, nó không phải là dễ dàng như chỉ cần thêm một thanh quy mô ... –

Trả lời

3

Có thư viện có tên ggsn, cho phép bạn tùy chỉnh thanh tỷ lệ và mũi tên hướng bắc.

ggplot() + 
    geom_path(aes(long, lat, group=group), data=worldUk, color="black", fill=NA) + 
    coord_equal() + 
    ggsn::scalebar(worldUk, dist = 100, st.size=3, height=0.01, dd2km = TRUE, model = 'WGS84') 

enter image description here

0

Tôi sẽ đề xuất chú thích(), cho phép bạn vẽ các đoạn có chiều dài thích hợp ngay trong khu vực vẽ đồ thị. Sau đó, bạn có thể thêm văn bản ở trên/dưới dưới dạng nhãn.

3

Tôi tìm thấy câu trả lời này trên http://editerna.free.fr/wp/?p=76 và tôi thấy nó đơn giản và hoạt động hoàn hảo vì vậy tôi phải chia sẻ nó!

Nó là đơn giản, đầu tiên dán đoạn mã dưới đây vào giao diện điều khiển của bạn (không cần chỉnh sửa)

library(maps) 
library(maptools) 
library(ggplot2) 
library(grid) 
#Then, we need a function to get the scale bar coordinates: 

# 
# Result # 
#--------# 
# Return a list whose elements are : 
# - rectangle : a data.frame containing the coordinates to draw the first rectangle ; 
# - rectangle2 : a data.frame containing the coordinates to draw the second rectangle ; 
# - legend : a data.frame containing the coordinates of the legend texts, and the texts as well. 
# 
# Arguments : # 
#-------------# 
# lon, lat : longitude and latitude of the bottom left point of the first rectangle to draw ; 
# distanceLon : length of each rectangle ; 
# distanceLat : width of each rectangle ; 
# distanceLegend : distance between rectangles and legend texts ; 
# dist.units : units of distance "km" (kilometers) (default), "nm" (nautical miles), "mi" (statute miles). createScaleBar <- 
function(lon,lat,distanceLon,distanceLat,distanceLegend, dist.units = 
"km"){ 
    # First rectangle 
    bottomRight <- gcDestination(lon = lon, lat = lat, bearing = 90, dist = distanceLon, dist.units = dist.units, model = "WGS84") 

    topLeft <- gcDestination(lon = lon, lat = lat, bearing = 0, dist = distanceLat, dist.units = dist.units, model = "WGS84") 
    rectangle <- cbind(lon=c(lon, lon, bottomRight[1,"long"], bottomRight[1,"long"], lon), 
    lat = c(lat, topLeft[1,"lat"], topLeft[1,"lat"],lat, lat)) 
    rectangle <- data.frame(rectangle, stringsAsFactors = FALSE) 

    # Second rectangle t right of the first rectangle 
    bottomRight2 <- gcDestination(lon = lon, lat = lat, bearing = 90, dist = distanceLon*2, dist.units = dist.units, model = "WGS84") 
    rectangle2 <- cbind(lon = c(bottomRight[1,"long"], bottomRight[1,"long"], bottomRight2[1,"long"], bottomRight2[1,"long"], 
bottomRight[1,"long"]), 
    lat=c(lat, topLeft[1,"lat"], topLeft[1,"lat"], lat, lat)) 
    rectangle2 <- data.frame(rectangle2, stringsAsFactors = FALSE) 

    # Now let's deal with the text 
    onTop <- gcDestination(lon = lon, lat = lat, bearing = 0, dist = distanceLegend, dist.units = dist.units, model = "WGS84") 
    onTop2 <- onTop3 <- onTop 
    onTop2[1,"long"] <- bottomRight[1,"long"] 
    onTop3[1,"long"] <- bottomRight2[1,"long"] 

    legend <- rbind(onTop, onTop2, onTop3) 
    legend <- data.frame(cbind(legend, text = c(0, distanceLon, distanceLon*2)), stringsAsFactors = FALSE, row.names = NULL) 
    return(list(rectangle = rectangle, rectangle2 = rectangle2, legend = legend)) } We also need a function to obtain the coordinates of the North arrow: 

# 
# Result # 
#--------# 
# Returns a list containing : 
# - res : coordinates to draw an arrow ; 
# - coordinates of the middle of the arrow (where the "N" will be plotted). 
# 
# Arguments : # 
#-------------# 
# scaleBar : result of createScaleBar() ; 
# length : desired length of the arrow ; 
# distance : distance between legend rectangles and the bottom of the arrow ; 
# dist.units : units of distance "km" (kilometers) (default), "nm" (nautical miles), "mi" (statute miles). createOrientationArrow <- 
function(scaleBar, length, distance = 1, dist.units = "km"){ 
    lon <- scaleBar$rectangle2[1,1] 
    lat <- scaleBar$rectangle2[1,2] 

    # Bottom point of the arrow 
    begPoint <- gcDestination(lon = lon, lat = lat, bearing = 0, dist = distance, dist.units = dist.units, model = "WGS84") 
    lon <- begPoint[1,"long"] 
    lat <- begPoint[1,"lat"] 

    # Let us create the endpoint 
    onTop <- gcDestination(lon = lon, lat = lat, bearing = 0, dist = length, dist.units = dist.units, model = "WGS84") 

    leftArrow <- gcDestination(lon = onTop[1,"long"], lat = onTop[1,"lat"], bearing = 225, dist = length/5, dist.units = 
dist.units, model = "WGS84") 

    rightArrow <- gcDestination(lon = onTop[1,"long"], lat = onTop[1,"lat"], bearing = 135, dist = length/5, dist.units = 
dist.units, model = "WGS84") 

    res <- rbind(
      cbind(x = lon, y = lat, xend = onTop[1,"long"], yend = onTop[1,"lat"]), 
      cbind(x = leftArrow[1,"long"], y = leftArrow[1,"lat"], xend = onTop[1,"long"], yend = onTop[1,"lat"]), 
      cbind(x = rightArrow[1,"long"], y = rightArrow[1,"lat"], xend = onTop[1,"long"], yend = onTop[1,"lat"])) 

    res <- as.data.frame(res, stringsAsFactors = FALSE) 

    # Coordinates from which "N" will be plotted 
    coordsN <- cbind(x = lon, y = (lat + onTop[1,"lat"])/2) 

    return(list(res = res, coordsN = coordsN)) } The last function enables the user to draw the elements: 

# 
# Result # 
#--------# 
# This function enables to draw a scale bar on a ggplot object, and optionally an orientation arrow # 
# Arguments : # 
#-------------# 
# lon, lat : longitude and latitude of the bottom left point of the first rectangle to draw ; 
# distanceLon : length of each rectangle ; 
# distanceLat : width of each rectangle ; 
# distanceLegend : distance between rectangles and legend texts ; 
# dist.units : units of distance "km" (kilometers) (by default), "nm" (nautical miles), "mi" (statute miles) ; 
# rec.fill, rec2.fill : filling colour of the rectangles (default to white, and black, resp.); 
# rec.colour, rec2.colour : colour of the rectangles (default to black for both); 
# legend.colour : legend colour (default to black); 
# legend.size : legend size (default to 3); 
# orientation : (boolean) if TRUE (default), adds an orientation arrow to the plot ; 
# arrow.length : length of the arrow (default to 500 km) ; 
# arrow.distance : distance between the scale bar and the bottom of the arrow (default to 300 km) ; 
# arrow.North.size : size of the "N" letter (default to 6). scaleBar <- function(lon, lat, distanceLon, distanceLat, distanceLegend, 
dist.unit = "km", rec.fill = "white", rec.colour = "black", rec2.fill 
= "black", rec2.colour = "black", legend.colour = "black", legend.size = 3, orientation = TRUE, arrow.length = 500, arrow.distance = 300, arrow.North.size = 6){ 
    laScaleBar <- createScaleBar(lon = lon, lat = lat, distanceLon = distanceLon, distanceLat = distanceLat, distanceLegend = 
distanceLegend, dist.unit = dist.unit) 
    # First rectangle 
    rectangle1 <- geom_polygon(data = laScaleBar$rectangle, aes(x = lon, y = lat), fill = rec.fill, colour = rec.colour) 

    # Second rectangle 
    rectangle2 <- geom_polygon(data = laScaleBar$rectangle2, aes(x = lon, y = lat), fill = rec2.fill, colour = rec2.colour) 

    # Legend 
    scaleBarLegend <- annotate("text", label = paste(laScaleBar$legend[,"text"], dist.unit, sep=""), x = 
laScaleBar$legend[,"long"], y = laScaleBar$legend[,"lat"], size = 
legend.size, colour = legend.colour) 

    res <- list(rectangle1, rectangle2, scaleBarLegend) 

    if(orientation){# Add an arrow pointing North 
     coordsArrow <- createOrientationArrow(scaleBar = laScaleBar, length = arrow.length, distance = arrow.distance, dist.unit = 
dist.unit) 
     arrow <- list(geom_segment(data = coordsArrow$res, aes(x = x, y = y, xend = xend, yend = yend)), annotate("text", label = "N", x = 
coordsArrow$coordsN[1,"x"], y = coordsArrow$coordsN[1,"y"], size = 
arrow.North.size, colour = "black")) 
     res <- c(res, arrow) 
    } 
    return(res) } 

Bây giờ, để vẽ lên một bản đồ!

Đầu tiên tạo ra bản đồ ggplot của bạn, và thêm thanh tỷ lệ như thêm một lớp, sử dụng «+» dấu:

your_ggplot_object -> your_ggplot_object + scaleBar(lon = -130, lat = 26, distanceLon = 500, 
distanceLat = 100, distanceLegend = 200, dist.unit = "km") 

On ví dụ trên, tôi gọi là «scaleBar» chức năng, và tôi chỉ định một số giá trị cho các đối số. Ví dụ, lon = -130, lat = 26 có nghĩa là tôi muốn điểm dưới cùng bên trái của hình chữ nhật ở mức (-130,26). Bạn cần phải xác định các giá trị khác của mỗi đối số theo những gì bạn muốn (có một mô tả của mỗi đối số trong tiêu đề của hàm).

+0

@Gregor done :) – CDav

+0

Giải pháp này dường như không hoạt động với ggmap(), nhưng dường như làm việc với ggplot(). bất kỳ manh mối nào về việc sử dụng điều này với ggmap? – jjunju

+0

Tôi gặp lỗi: 'Không biết cách tự động chọn tỷ lệ cho đối tượng của hàm kiểu. Mặc định liên tục Lỗi trong data.frame (x = c (13.15, 13.15, 13.2235616636229, 13.2235616636229,: đối số ngụ ý số lượng hàng khác nhau: 5, 0' Tôi có thể làm gì? –

Các vấn đề liên quan