Search code examples
rplotscale

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?


Solution

  • 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")
    

    enter image description here