For example, this works: x = seq(-100, 1000, 25) y = x * x plot(x,y, xaxt="n") axis(1,x,FALSE,tcl=-0.3) axis(1,x[x %% 100 ==0]) It creates two axis objects and the values of the x-axis are the labels. The following scenario is more difficult, because it uses 'image' to plot a grid of values: a = matrix(rnorm(100),ncol=10) image(1:ncol(a), 1:nrow(a), a, xaxt="n", yaxt="n") # adding arbitrary categorical labels to y-axis ylabels=c('A','B','C','D','E','F','G','H','I','J') axis(2, at=1:10, labels=ylabels, las=HORIZONTAL<-1) # adding arbitrary categorical labels to x-axis, # for every nth category; first add tick marks, # then the labels axis(1, at=1:10, FALSE) xlabels=c('A','','C','','E','','G','','I','') # this is length=10 axis(1, at=1:10, labels=xlabels) This works, but when using axis, the 'at=1:10' and the length(xlabels) must be the same length. Is it ever possible to specify axis when these values are not the same length? That is, the following does not work: x = seq(-100, 1000, 25) y = x * x plot(x,y, xaxt="n") axis(1,x,labels=x[x %% 100 ==0]) Error in axis(side, at, labels, tick, line, pos, outer, font, lty, lwd, : 'at' and 'label' lengths differ, 45 != 12 Would it be possible to have axis automatically find the right location within the x-axis for these labels? Perhaps something like: xt = (x %% 100 == 0) xlabels = x xlabels[!xt] = '' This would leave the intermittent label values. I guess a for loop is needed to generate xt for irregular intervals in the labels (eg, c(10, 50, 75, 150, 400)). If the axis command could do this, it would not be necessary to call it twice to get a subset of labels for all the tick marks. That is, it would create tick marks for the 'at' specification and labels at the 'labels' specification (with no restraint on these being equal lengths). Regards, Darren