简体   繁体   中英

How to add a scale bar in R?

Lets say I want to have a plot and lose the box in R. But still I would need a scale bar so one can understand the scaling. I didn't find a solution.

plot(1,1, type="n", xlim=c(0,5), ylim=c(0,5))

When I use the scalebar function from the raster package, the scaling is not right:

require(raster)
scalebar(1)

The added scalebar is too short to represent 1 in the x axis. I tried to find something else, but most scalebar functions are related to maps.

edit: So what I want is something like this:

plot(1,1, type="n", xlim=c(0,5), ylim=c(0,5)
             , yaxt="n",
             xaxt="n", frame.plot=F, ann=F
    # adding a blank plot without the axes
     )

#adding some simple function
x=c(1:5)
y=x*x
lines(x=x, y=y)

#defining where the scale bar should appear
lines(x=c(4,5), y=c(5,5))

#placing the text right under the line
text(x=4.5, y=5, pos=1, label="1 km")

Is there an easier way to do something like this?

There might be a function that does what you want, but you can also create your own function that will hopefully serve well enough. See below for one possibility. You can of course adjust the function settings to get the positioning you want. In particular, I've included yadj as an argument to the function, with a default value of 1.5. You can change this if the scalebar label isn't positioned properly under the scale line.

If the x-axis spans a larger range than the values used below, you'll want to adjust the x-coordinates of the scale line so that it spans 10, 100, etc. x-units, as the case may be. If you want to get fancy, you can have the function itself determine how many x-units to span, based on the x-range of the plot and then use the magnitude of that span in the units label.

# Function to add a scalebar to a base-graphics plot
myScalebar = function(units_label, yadj=1.5) {

  # Get plot coordinates
  pc = par("usr") 

  # Position scale line between last two major x-axis tick marks
  # and 1/10th of the total y-range above the lower y-axis coordinate
  lines(c(floor(pc[2]-1),floor(pc[2])),     
        rep(pc[3] + 0.1*(pc[4] - pc[3]), 2))

  # Place the units label at the midpoint of and just below the scale line
  text(x=mean(c(floor(pc[2]-1), floor(pc[2]))), 
       y=pc[3] + 0.1*(pc[4] - pc[3]),
       label=units_label, adj=c(0.5, yadj))
}

# Now redo your plot
# Start with blank plot
plot(1,1, type="n", xlim=c(0,5), ylim=c(0,5), 
     yaxt="n", xaxt="n", frame.plot=F, ann=F)

# Add a simple function
x=c(1:5)
y=x*x
lines(x=x, y=y)

# Add scalebar
myScalebar("1 km")

在此处输入图片说明

I usually use this sort of function that allows for lots of flexibility across plots. I have expanded the variables names to help with debugging. Please note: this is designed to work with raster converted to utms only (don't use geographic projections).

ScaleBar <- function(reference_raster_utm, round_to_nearest_km, width_percent, y_percent_from_bottom, x_percent_from_left, y_text_percent_from_bottom, ...) {
    # Round by max to nearest... e.g. 5 km 
    mround <- function(x,base){ 
        base*round(x/base) 
    }   
    # scale bar size adjustment to avoid decimals
        scale_size <- ((xmax(reference_raster_utm)-xmin(reference_raster_utm))*width_percent)/1000
        scale_size_adj <- mround(scale_size, round_to_nearest_km)
        scale_size_adj_plot <- (scale_size_adj*1000)/2
    # Horizontal percent position (x) for scale bar
        x_position <- ((xmax(reference_raster_utm)-xmin(reference_raster_utm))*x_percent_from_left)+xmin(reference_raster_utm)
    # Vertical percent position y for scale bar
        y_position <- ((ymax(reference_raster_utm)-ymin(reference_raster_utm))*y_percent_from_bottom)+ymin(reference_raster_utm)
        y_position_text <- ((ymax(reference_raster_utm)-ymin(reference_raster_utm))*y_text_percent_from_bottom)+ymin(reference_raster_utm)
    # Draw line on plot
        library(sp)
        x_ends <- c((x_position-scale_size_adj_plot), (x_position+scale_size_adj_plot))
        y_ends <- c((y_position), (y_position))
        scale_bar_line <- SpatialLines(list(Lines(Line(cbind(x_ends, y_ends)), ID="length")))
        projection(scale_bar_line) <- projection(reference_raster_utm)
        plot(scale_bar_line, add=TRUE, ...)
        text(x_position, y_position_text, paste0(scale_size_adj, "km"))
}

Arguments :

  • reference_raster_utm: One of your personal raster files to source extent/projection from.
  • round_to_nearest_km: round to nearest kilometre eg max out on 2km, 5km ect.
  • width_percent: percent of plot width that the scale bar should cover (eg big 50% small 10%).
  • y_percent_from_bottom: vertical position from bottom. 0% at bottom, 100% at top, 50% in the middle.
  • x_percent_from_left: horizontal position from left. 0% at left, 100% at right, 50% in the middle.
  • y_text_percent_from_bottom: same as y_percent_from_bottom but for text.

Example :

plot(my_raster)

ScaleBar(reference_raster_utm=my_raster, round_to_nearest_km=5, width_percent=0.25, y_percent_from_bottom=0.10, x_percent_from_left=0.50, y_text_percent_from_bottom=0.07, lwd=2)

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM