Skip to content

I want axes that cross

12 messages · Daniel Moreira, Marc Schwartz, Paul Johnson +3 more

#
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:

   |
   |         *
   |           *
   |     *
---|-----------------

However, when we use plot with axes=F and then use the axis commands
to add the axes, they do not cross over each other. We get


   |         *
   |           *
         *
       ----------

The axes are not wide enough to cover the entire range of the data. We
do not want to add a box() command, which is a usual answer for this,
because we don't want to draw on top or the side.

Here's my test case:

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

Can I cause the 2 axes to "cross" as desired?

The axis help says the axis is clipped at the plot region, but it
seems to get clipped even more narrowly thanthat.

I've been searching in r-help quite a bit and am a little surprised
how difficult this is....
#
on 02/13/2009 01:25 PM Paul Johnson wrote:
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.

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.

See ?par for more information.

HTH,

Marc Schwartz
#
On Fri, Feb 13, 2009 at 1:51 PM, Marc Schwartz
<marc_schwartz at comcast.net> wrote:
Thanks, I did not find bty under ?box, but found it under par after
you pointed it out.

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:

   |
   |
 _|______
   |

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

  
    
#
On Fri, Feb 13, 2009 at 1:42 PM, Daniel Moreira <daniel.moreira at duke.edu> wrote:
If you actually ran that code and still suggest it as the fix, then I
think you must be joking.  Pushing the axes into the middle of the
data cloud in order to make them cross is certainly not making a very
nice looking plot. Not only are there observations outside the area
framed by the axes, but there are axis labels that are overlapped by
observations and by the axes themselves.

PJ
#
On Fri, 13 Feb 2009, Paul Johnson wrote:

            
Paul,

If you use
 	axis( ... , at = c(low,high), xpd=TRUE, col='green',
 		labels=FALSE, lwd.tick=0)

for suitably chosen values of low and high (and ... ), I think you can
get what you want. It will overwrite your axis, but if you choose the same 
color, this won't be noticed.

HTH,

Chuck
Charles C. Berry                            (858) 534-2098
                                             Dept of Family/Preventive Medicine
E mailto:cberry at tajo.ucsd.edu	            UC San Diego
http://famprevmed.ucsd.edu/faculty/cberry/  La Jolla, San Diego 92093-0901
#
I think you ought to worry a bit about who might be laughing at whom.  
You are asking for a plot with rather unnatural behavior and  
potentially very misleading to the audience. Here it is, but you bear  
full responsibility for any consequences:

plot(x,y,type="n", axes=F, xlim=c(min(x)-1, max(x)),  
ylim=c(min(y)-1,max(y)))
points(x,y, pch="$",cex=0.7, col=z)
axis(1, col="green", col.axis="green",pos=-1)
axis(2, col="red", col.axis="red", pos=-2.5)
#
on 02/13/2009 02:19 PM Paul Johnson wrote:
'bty' is referenced in ?box as a '...' argument, though the detailed
options are defined in ?par.
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?
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.
...
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
2 days later
#
On Fri, Feb 13, 2009 at 3:14 PM, Marc Schwartz
<marc_schwartz at comcast.net> wrote:
Thanks, Marc and everybody.

This last suggestion produces the graph I was trying for.

The other approaches that people suggest, using pos or xaxp, produce
other undesired changes in the tick marks or the position of the axes
relative to the data. xaxp offers the promise of a more intuitive
solution, except that, when using it, the tick marks are pushed off in
a bad way.  Your use of segments to draw the extensions of the axes
was the first intuition I had, but I did not know about the trick you
used to retrieve the size of the usr box.

More secrets of par, revealed.

Have you ever seen a drawing of the regions of an R plot with the
terminology that is used for parts?  Until I saw your example code, I
had not understood that the plot axes are placed at the absolute edge
of the user plotting region, for example.
#
Hi Paul,
springs to mind is Alzola & Harrell's "An Introduction to S and the Hmisc
and Design Libraries,? which you can download from the Contributed
Documentation link on CRAN.

Chap. 4 of MASS by Venables & Ripley (4th ed.) will also give you what you
want.

Regards, Mark.
Paul Johnson-11 wrote:

  
    
#
I would also add:

1. Chapter 12 in "An Introduction to R"

2. Chapter 3 in Paul's "R Graphics" book:

  http://www.stat.auckland.ac.nz/~paul/RGraphics/rgraphics.html

Note that the figures and code used for the graphics in the above
chapter are available here:

http://www.stat.auckland.ac.nz/~paul/RGraphics/chapter3.html

HTH,

Marc
on 02/16/2009 03:14 AM Mark Difford wrote: