Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

x axis is too short in R plot.default

Tags:

plot

r

axis

My x axis is too short.

My Plot

d <- data.frame(x = c(120,200,300), y = rep(1,3))

 plot(d$x, 
      d$y,
      xlim = c(min(d$x), max(d$x)),
      axes = FALSE,
      xlab = "",
      ylab = "")

axis(1, lwd = 2)

Clearly this is not ideal. I know there are numerous solutions for a single instance of plotting. However, I'm programmatically generating numerous of such graphs with difference x values. I therefore need a solution which is general and is directly applicable to different x values.

Below is some brain-storming code:

 #This works but the tick marks are ugly.  I also can't control lwd of axis
 plot(d$x, 
      d$y,
      yaxt="n",
      frame.plot = FALSE,
      xlab = "",
      ylab = "",
      xaxp = c(120, 300, 50)) 

 #this is the solution for this particular case, however, it would not work in general
 plot(d$x, 
      d$y,
      xlim = c(min(d$x)-20, max(d$x)),
      axes = FALSE,
      xlab = "",
      ylab = "")

axis(1, lwd = 2)    

Any thoughts?

like image 886
Jacob H Avatar asked Mar 05 '26 16:03

Jacob H


1 Answers

Here's a method using base R graphics. The logic is similar to the ggplot2 answer. The code below sets the x-range to the nearest multiples of 50 below and above the range of the data and puts ticks marks at every multiple of 50. You can add fancier logic if you want to vary either of these dynamically, based on the range of the data for different plots.

xfun calculates the minimum and maximum x-limits. tick.dist sets the distance we want between tick marks in the graph. The default is set to 50. So, by default, when which="min", xfun returns the largest multiple of 50 that is less than value. When which="max", xfun returns the large multiple of 50 that is greater than value.

xfun = function(value, which, tick.dist=50) {

  # Calculate minimum x-limit
  if(which=="min") {
    return(value - value %% tick.dist)
  }

  # Calculate maximum x-limit
  if(which=="max") {
    return(value + (tick.dist - value %% tick.dist))
  }
}

Now we create four sample plots.

par(mfrow=c(2,2))

# Try out various ranges for the x-values
x_vals = c(-23, 56, 80, 123)

# Set distance between tick marks
tick.dist=50

for (i in 1:length(x_vals)) {
  # Create fake data
  d <- data.frame(x=runif(10, x_vals[i], x_vals[i] + 220), y = rep(3,10))  

  # Set x limits and number of tick marks
  xmin = xfun(min(d$x), "min", tick.dist) 
  xmax = xfun(max(d$x), "max", tick.dist) 
  nticks = as.integer((xmax - xmin)/tick.dist)

  # Plot
  plot(d$x, d$y, xaxt="n", yaxt="n", frame.plot = FALSE,
       xlab = "", ylab = "", xlim=c(xmin, xmax)) 

  # xaxp controls location of min and max x-axis tick marks
  #  as well as the total number of tick marks. 
  #  See ?par("xaxp") for more info.
  axis(1, lwd = 2, xaxp = c(xmin, xmax, nticks))
}

enter image description here

like image 58
eipi10 Avatar answered Mar 07 '26 09:03

eipi10



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!