Reputation: 10215
To compare the result of multiple medical variables with a very large difference in range I want to create a scatterplot like the one below
with per-panel same axis horizontally and vertically,
fixed aspect, so that the slope=1 line goes through the corners.
-
library(ggplot2)
set.seed(11)
d = rbind(
data.frame(what = "a", v1 = rnorm(20)+0.2, v2 = rnorm(20)),
data.frame(what = "b", v1 = rnorm(20, 100, 10)+20, v2 = rnorm(20, 100,10)))
ggplot(d, aes(x = v1, y = v2 )) +
geom_point() +
geom_abline(slope = 1) +
facet_wrap(~what, scales = "free") +
theme(aspect.ratio = 1) +
coord_fixed(ratio = 1) + # No effect?
stat_ellipse()
I am aware of the hard way to get this with precomputed limits. Setting individual axis limits with facet_wrap and scales = "free" in ggplot2
Upvotes: 6
Views: 324
Reputation: 2026
If you invisibly plot everything with x and y reversed each facet will have identical x and y axes.
library(ggplot2)
set.seed(11)
d = rbind(
data.frame(what = "a", v1 = rnorm(20)+0.2, v2 = rnorm(20)),
data.frame(what = "b", v1 = rnorm(20, 100, 10)+20, v2 = rnorm(20, 100,10)))
ggplot(d ) +
geom_point(aes(x = v1, y = v2 )) +
geom_blank(aes(x = v2, y = v1 )) +
geom_abline(slope = 1) +
facet_wrap(~what, scales = "free") +
stat_ellipse(aes(x = v1, y = v2 )) +
stat_ellipse(aes(x = v2, y = v1 ), alpha=0)
Upvotes: 1
Reputation: 10215
I ended up using the solution @baptiste suggested in Setting individual axis limits with facet_wrap and scales = "free" in ggplot2 with a dummy geom_blank
. It's not perfect, though, because ggplots insists on using its own ideas about scaling, so the line does not go through the corners.
library(ggplot2)
set.seed(11)
d = rbind(
data.frame(what = "a", v1 = rnorm(20) + 0.2, v2 = rnorm(20)),
data.frame(what = "b", v1 = rnorm(20, 100, 10) + 20, v2 = rnorm(20, 100,10)))
drange = do.call(rbind, by(d, d$what, function(x) extendrange(c(x$v1, x$v2))))
dummy = data.frame(what = rownames(drange), v1 = drange[,1], v2 = drange[,2] )
ggplot(d, aes(x = v1, y = v2 )) +
geom_point() +
geom_abline(slope = 1) +
theme(aspect.ratio = 1) +
coord_fixed(ratio = 1, expand = FALSE) +
stat_ellipse() +
geom_blank(data = dummy) +
facet_wrap(~what, scales = "free")
And here the solution with lattice, which simply does what you ask it to do.
lattice::xyplot(v2~v1|what, data = d, aspect = 1, pch = 16,
scales = list(relation = "free"),
panel = function(x,y, ...){
lattice::panel.xyplot(x, y, ...)
lattice::panel.abline(a = 0, b = 1)
},
prepanel = function(x, y, ...){
lim = c(min(x, y), max(x, y))
list(xlim = lim, ylim = lim)
})
Upvotes: 0