[R] I want axes that cross

Marc Schwartz marc_schwartz at comcast.net
Fri Feb 13 22:14:00 CET 2009


on 02/13/2009 02:19 PM Paul Johnson wrote:
> On Fri, Feb 13, 2009 at 1:51 PM, Marc Schwartz
> <marc_schwartz at comcast.net> wrote:
>> on 02/13/2009 01:25 PM Paul Johnson wrote:
>>> Hello, everybody.
>>>
>>> A student asked me a howto question I can't answer.  We want the
>>> length of the drawn axes to fill the full width and height of the
>>> plot, like so:
> 
>> Paul,
>>
>> I am guessing that you want:
>>
>> x <- rnorm(100)
>> z <- gl(2,50)
>> y <- rnorm(100, mean= 1.8*as.numeric(z))
>>
>> plot(x,y,type="n", axes=F)
>> points(x,y, pch="$",cex=0.7, col=z)
>> axis(1, col="green", col.axis="green")
>> axis(2, col="red", col.axis="red")
>>
>> # Draw the box like an "L" on the bottom and left only
>> box(bty = "l")
>>
>>
>> Note that you can specify which sides the 'box' is created upon by using
>> the 'bty' argument. See ?box for more information.
> 
> Thanks, I did not find bty under ?box, but found it under par after
> you pointed it out.

'bty' is referenced in ?box as a '...' argument, though the detailed
options are defined in ?par.

> That does not get the correct output, however, because the black box
> covers over my 2 different colored axes.
> 
> Even if I weren't color-conscious, it gives me this:
> 
> |
> |
> |_______
> 
> not crossed axes, which I want:
> 
>    |
>    |
>  _|______
>    |

OK...so if I am reading this more clearly, you don't want them to simply
join in the corner, but to actually cross for some length?

> I'm putting in a seed so we will both see the same things in this example.
> 
> set.seed(1233240)
> x <- rnorm(100)
> z <- gl(2,50)
> y <- rnorm(100, mean= 1.8*as.numeric(z))
> plot(x,y,type="n", axes=F)
> points(x,y, pch="$",cex=0.7, col=z)
> axis(1, col="green", col.axis="green")
> axis(2, col="red", col.axis="red")

> # MS recomends:
>  # Draw the box like an "L" on the bottom and left only
>  box(bty = "l")
> 
>> Also, by default, the axes extend the range of 'x' and 'y'  by 4%. You
>> can use 'xaxs = i' and 'yaxs = i' in the plot() call to restrict the
>> axes to the true ranges of 'x' and 'y'.  This would be important, for
>> example, when you want the lower left hand corner of the plot to be at
>> exact coordinates such as 0,0.
> 
> I would be delighted if the axes really did reach 4% outside the data.
> But they don't.  I've seen that same thing you are referring to in the
> documentation, but there's something wrong about it, In my example
> code, we should see the same thing now I've put in a seed. The axes
> are smaller than the data range, not equal to 1.04 times the data
> range. I see several observations in the graph that are "off the
> charts", they are above the highest value of the y axis, or below the
> lowest axis value. Similarly, there are observations smaller than the
> low end of the x axis and bigger than the largest x axis value.
> 
> The 4% may be the plot region's size, but it is surely not the length
> of the axis that is drawn?

Yes, strictly speaking it is the plot region's dimensions that are
extended by 4%, when these two parameters are set to 'r', which is the
default.

However, the actual drawn axes *may* be affected by this, since the data
range has been extended and this will affect the default calculation of
the axis tick marks, which is dependent upon the resultant range.

>From ?par for 'xaxs':

...
Style "r" (regular) first extends the data range by 4 percent at each
end and then finds an axis with pretty labels that fits within the
extended range. Style "i" (internal) just finds an axis with pretty
labels that fits within the original data range.
...


OK, so given all of the above, something like the following should work:

set.seed(1233240)
x <- rnorm(100)
z <- gl(2,50)
y <- rnorm(100, mean = 1.8 * as.numeric(z))

# Calculate a new range, subtracting a definable value
# from the min of each vector for the new minimum
# Adust the 0.25 as may be needed
X <- c(min(x) - 0.25, max(x))
Y <- c(min(y) - 0.25, max(y))

# Use 'X' and "Y' here, not 'x' and 'y'
# So that the plot region is extended appropriately
plot(X, Y, type = "n", axes = F, xlab = "x", ylab = "y")

points(x, y, pch = "$", cex = 0.7, col = z)

# DO use 'pos'...
axis(1, pos = Y[1], col = "green", col.axis = "green")
axis(2, pos = X[1], col = "red", col.axis = "red")

# get the plot region boundaries
usr <- par("usr")

segments(X[1], usr[3], X[1], usr[4], col = "red")
segments(usr[1], Y[1], usr[2], Y[1], col = "green")


HTH,

Marc




More information about the R-help mailing list