12

I want an hist and a density on the same plot, I'm trying this:

myPlot <- plot(density(m[,1])), main="", xlab="", ylab="")
par(new=TRUE)

Oldxlim <- myPlot$xlim
Oldylim <- myPlot$ylim

hist(m[,3],xlim=Oldxlim,ylim=Oldylim,prob=TRUE)

but I can't access myPlot's xlim and ylim.

Is there a way to get them from myPlot? What else should I do instead?

jimifiki
  • 5,377
  • 2
  • 34
  • 60

5 Answers5

7

Using par(new=TRUE) is rarely, if ever, the best solution. Many plotting functions have an option like add=TRUE that will add to the existing plot (including the plotting function for histograms as mentioned in the comments).

If you really need to do it this way then look at the usr argument to the par function, doing mylims <- par("usr") will give the x and y limits of the existing plot in user coordinates. However when you use that information on a new plot make sure to set xaxs='i' or the actual coordinates used in the new plot will be extended by 4% beyond what you specify.

The functions grconvertX and grconvertY are also useful to know. They could be used or this purpose, but are probably overkill compared to par("usr"), but they can be useful for finding the limits in other coordinate systems, or finding values like the middle of the plotting region in user coordinates.

Greg Snow
  • 48,497
  • 6
  • 83
  • 110
5

Have you considered specifying your own xlim and ylim in the first plot (setting them to appropriate values) then just using those values again to set the limits on the histogram in the second plot?

Just by plotting density on its own you should be able to work out sensible values for the minimum and maximum values for both axes then replace xmin, xmax, ymin and ymax for those values in the code below.

something like;

myPlot <- plot(density(m[,1])), main="", xlab="", ylab="", xlim =c(xmin, xmax), ylim = c(ymin, ymax)

par(new=TRUE)

hist(m[,3],xlim=c(min, max),ylim=c(min, max),prob=TRUE)
Adam Kimberley
  • 879
  • 5
  • 12
5

If for any reason you are not able to use range() to get the limits, I'd follow @Greg's suggestion. This would only work if the par parameters "xaxs" and "yaxs" are set to "s" (which is the default) and the coordinate range is extended by 4%:

plot(seq(0.8,9.8,1), 10:19)
usr <- par('usr')
xr <- (usr[2] - usr[1]) / 27 # 27 = (100 + 2*4) / 4
yr <- (usr[4] - usr[3]) / 27
xlim <- c(usr[1] + xr, usr[2] - xr)
ylim <- c(usr[3] + yr, usr[4] - yr)
dojuba
  • 2,199
  • 1
  • 18
  • 16
2

I think the best solution is to fix them when you plot your density.

Otherwise hacing in the code of plot.default (plot.R)

xlab=""
ylab=""
log =""
xy <- xy.coords(x, y, xlab, ylab, log)
xlim1 <- range(xy$x[is.finite(xy$x)])
ylim1 <- range(xy$y[is.finite(xy$y)])

or to use the code above to generate xlim and ylim then call your plot for density

dd <- density(c(-20,rep(0,98),20))
plot(dd,xlim=xlim1,ylim=ylim1)
x <- rchisq(100, df = 4)
hist(x,xlim=xlim1,ylim=xlim1,prob=TRUE,add=TRUE)

enter image description here

agstudy
  • 119,832
  • 17
  • 199
  • 261
-1

Why not use ggplot2?

library(ggplot2)

set.seed(42)
df <- data.frame(x = rnorm(500,mean=10,sd=5),y = rlnorm(500,sdlog=1.1))

p1 <- ggplot(df) + 
  geom_histogram(aes(x=y,y = ..density..),binwidth=2) +
  geom_density(aes(x=x),fill="green",alpha=0.3) 
print(p1)

density and hist

Roland
  • 127,288
  • 10
  • 191
  • 288