向ggplot地图添加比例尺 [英] Adding scale bar to ggplot map

查看:2060
本文介绍了向ggplot地图添加比例尺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 ggplot2 中制作了这张地图:

 库(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()



使用photoshop,我已经在地图上添加了比例尺。如何使用 ggplot2 添加类似的比例尺?这个帖子添加了一个比例尺,但是该条不指向距离: map-ggplot2上的比例尺和北箭

解决方案

我在 http://editerna.free.fr/wp/?p=76 ,我发现它很简单,工作完美所以我必须分享吧!



很简单,首先将下面的代码粘贴到控制台中(无需编辑)

库(maptools)
库(ggplot2)
库(网格)
#然后,我们需要一个函数来获取比例bar坐标:


#结果#
#--------#
#返回一个列表,其元素为:
# - rectangle:包含绘制第一个矩形坐标的data.frame;
# - rectangle2:包含绘制第二个矩形的坐标的data.frame;
# - 图例:包含图例文本坐标的数据框,以及文本。

#参数:#
#-------------#
#lon,lat:左下角的经度和纬度第一个矩形画;
#distanceLon:每个矩形的长度;
#distanceLat:每个矩形的宽度;
#distanceLegend:矩形和图例文字之间的距离;
#dist.units:距离单位km(公里)(默认),nm(海里),mi(法定里程)。 createScaleBar< -
函数(lon,lat,distanceLon,distanceLat,distanceLegend,dist.units =
km){
#第一个矩形
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))
矩形< - data.frame(rectangle,stringsAsFactors = FALSE)

#第一个矩形右侧的第二个矩形
bottomRight2 < - gcDestination(lon = lon,lat = lat, = 90,dist = distanceLon * 2,dist.units = dist.units,model =WGS84)
rectangle2 < - cbind(lon = c(bottomRight [1,long],bottomRight [ long],bottomRight2 [1,long],bottomRight2 [1,lo ng],
bottomRight [1,long]),
lat = c(lat,topLeft [1,lat],topLeft [1,lat],lat,lat) )
rectangle2< - data.frame(rectangle2,stringsAsFactors = FALSE)

#现在我们来处理文本
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 (矩形=矩形,矩形2 =矩形2,图例=图例))}我们还需要一个函数来获取北箭头的坐标:


#结果#
# --------#
#返回一个列表,包含:
# - res:坐标绘制箭头;
# - 箭头中间的坐标(将绘制N)。

#参数:#
#-------------#
#scaleBar:createScaleBar()的结果;
#长度:所需长度的箭头;
#距离:图例矩形和箭头底部之间的距离;
#dist.units:距离单位km(公里)(默认),nm(海里),mi(法定里程)。 createOrientationArrow< -
函数(scaleBar,length,distance = 1,dist.units =km){
lon< - scaleBar $ rectangle2 [1,1]
lat& - scaleBar $ rectangle2 [1,2]

#箭头的底点
begPoint< - gcDestination(lon = lon,lat = lat,bearing = 0,dist = distance,dist $。
lon< - begPoint [1,long]
lat< - begPoint [1,lat]

#让我们创建一个端点
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], = 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 。框架(res,stringsAsFactors = FALSE)

#将绘制N的坐标
coordsN < - cbind(x = lon,y =(lat + onTop [ lat])/ 2)

return(list(res = res,coordsN = coordsN))}最后一个函数使用户可以绘制元素:


#结果#
#--------#
#此功能可以在ggplot对象上绘制一个比例尺,并且可以选择方向箭头#
#参数:#
#-------------#
#lon,lat:绘制第一个矩形左下角的经度和纬度;
#distanceLon:每个矩形的长度;
#distanceLat:每个矩形的宽度;
#distanceLegend:矩形和图例文字之间的距离;
#dist.units:距离单位km(公里)(默认),nm(海里),mi(法定里程);
#rec.fill,rec2.fill:填充矩形的颜色(默认为白色,黑色,分别);
#rec.colour,rec2.colour:矩形颜色(两者默认为黑色);
#legend.colour:图例颜色(默认为黑色);
#legend.size:图例大小(默认为3);
#orientation:(boolean)如果为TRUE(默认),向绘图添加方向箭头;
#arrow.length:箭头长度(默认为500公里);
#arrow.distance:比例尺和箭头底部之间的距离(默认为300公里);
#arrow.North.size:N字母的大小(默认为6)。 scaleBar< - 函数(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)
#第一个矩形
rectangle1< - geom_polygon(data = laScaleBar $ rectangle,aes(x = lon,y = lat),fill = rec.fill,color = rec.colour)

#第二个矩形
rectangle2< - geom_polygon(data = laScaleBar $ rectangle2,aes(x = lon,y = lat),fill = rec2.fill,color = rec2.colour)

#图例
scaleBarLegend< - annotate(text,label = paste(laScaleBar $ legend [,text],dist.unit,sep =),x =
laScaleBar $ legend [ 长],y = laScaleBar $ legend [,lat],size =
legend.size,color = legend.colour)

res < - list(rectangle1,rectangle2,scaleBarLegend)

if(orientation){#添加一个箭头指向北
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 N,x =
coordsArrow $ coordsN [1,x],y = coordsArrow $ coordsN [1,y],size =
arrow.North.size,color =black ))
res< - c(res,arrow)
}
return(res)}

现在,绘制一张地图!



首先创建您的ggplot地图,并使用«+»符号添加比例尺作为额外的图层:

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

在上面的例子中,我调用了scaleBar函数,并为参数指定了一些值。例如,lon = -130,lat = 26表示我想要矩形的左下角在(-130,26)。您需要根据需要定义每个参数的其他值(功能标题中每个参数的描述)。


I've produced this map in ggplot2:

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()

Using photoshop, I've added a scale bar to the map. How can I add a similar scale bar using ggplot2? This post adds a scale bar, but the bar doesn't refer to distance: scale bar and north arrow on map-ggplot2

解决方案

I found this answer on http://editerna.free.fr/wp/?p=76 and I found it simple and worked perfectly so I must share it!

It is simple, first paste the code below into your console (no need for editing)

 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) }

Now, to plot onto a map!

First create your ggplot map, and add the scale bar as an extra layer, using the « + » sign:

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

On the example above, I call the « scaleBar » function, and I specify some values for the arguments. For instance, lon = -130, lat = 26 means I want the bottom left point of the rectangle to be at (-130,26). You need to define the other values of each argument according to what you want (there is a description of each argument in the header of the function).

这篇关于向ggplot地图添加比例尺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆