[This article was first published on Learning R, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
This is the 12th post in a series attempting to recreate the figures in Lattice: Multivariate Data Visualization with R (R code available here) with ggplot2.
Previous parts in this series: Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9, Part 10, Part 11.
Chapter 13 – Advanced Panel Functions
Topics covered:
- Built-in panel and accessors functions
- Examples
Figure 13.1
> library(lattice) > library(ggplot2) |
> grid <- data.frame(p = 11:30, q = 10) > grid$k <- with(grid, factor(p/q)) |
> panel.hypotrochoid <- function(r, d, cycles = 10, density = 30) { + if (missing(r)) + r <- runif(1, 0.25, 0.75) + if (missing(d)) + d <- runif(1, 0.25 * r, r) + t <- 2 * pi * seq(0, cycles, by = 1/density) + x <- (1 - r) * cos(t) + d * cos((1 - r) * t/r) + y <- (1 - r) * sin(t) - d * sin((1 - r) * t/r) + panel.lines(x, y) + } > panel.hypocycloid <- function(x, y, cycles = x, density = 30) { + panel.hypotrochoid(r = x/y, d = x/y, cycles = cycles, + density = density) + } > prepanel.hypocycloid <- function(x, y) { + list(xlim = c(-1, 1), ylim = c(-1, 1)) + } |
lattice
> pl <- xyplot(p ~ q | k, grid, aspect = 1, scales = list(draw = FALSE), + prepanel = prepanel.hypocycloid, panel = panel.hypocycloid) > print(pl) |
ggplot2
> panel.hypotrochoid.gg <- function(r, d, cycles = 10, + density = 30) { + if (missing(r)) + r <- runif(1, 0.25, 0.75) + if (missing(d)) + d <- runif(1, 0.25 * r, r) + t <- 2 * pi * seq(0, cycles, by = 1/density) + x <- (1 - r) * cos(t) + d * cos((1 - r) * t/r) + y <- (1 - r) * sin(t) - d * sin((1 - r) * t/r) + data.frame(x, y) + } > panel.hypocycloid.gg <- function(x, y, cycles = x, density = 30) { + panel.hypotrochoid.gg(r = x/y, d = x/y, cycles = cycles, + density = density) + } |
Note |
panel.lines(x, y) replaced with data.frame(x, y) in the panel.hypotrochoid.gg function. |
> df <- ddply(grid, .(p, q, k), function(df) { + with(df, panel.hypocycloid.gg(q, p)) + }) |
> pg <- ggplot(df, aes(x, y)) + geom_path() + facet_wrap(~k, + ncol = 4) + scale_x_continuous("", breaks = NA) + + scale_y_continuous("", breaks = NA) > print(pg) |
Figure 13.2
lattice
> set.seed(20070706) |
> pl <- xyplot(c(-1, 1) ~ c(-1, 1), aspect = 1, cycles = 15, + scales = list(draw = FALSE), xlab = "", ylab = "", + panel = panel.hypotrochoid) > print(pl[rep(1, 42)]) |
ggplot2
> df2 <- ldply(rep(1:42), function(k) { + data.frame(k, panel.hypotrochoid.gg(cycles = 15)) + }) |
> pg <- ggplot(df2, aes(x, y)) + geom_path() + facet_wrap(~k, + ncol = 6) + scale_x_continuous("", breaks = NA) + + scale_y_continuous("", breaks = NA) + opts(panel.margin = 0, + strip.text.x = theme_blank()) > print(pg) |
Figure 13.3
> library("logspline") |
lattice
> prepanel.ls <- function(x, n = 50, ...) { + fit <- logspline(x) + xx <- do.breaks(range(x), n) + yy <- dlogspline(xx, fit) + list(ylim = c(0, max(yy))) + } > panel.ls <- function(x, n = 50, ...) { + fit <- logspline(x) + xx <- do.breaks(range(x), n) + yy <- dlogspline(xx, fit) + panel.lines(xx, yy, ...) + } |
> faithful$Eruptions <- equal.count(faithful$eruptions, + 4) |
> pl <- densityplot(~waiting | Eruptions, data = faithful, + prepanel = prepanel.ls, panel = panel.ls) > print(pl) |
ggplot2
> fn <- function(data = faithful$eruptions, number = 4, + ...) { + intrv <<- as.data.frame(co.intervals(data, number, + ...)) + eruptions <- sort(unique(data)) + intervals <- ldply(eruptions, function(x) { + t(as.numeric(x < intrv$V2 & x > intrv$V1)) + }) + tmp <- melt(cbind(eruptions, intervals), id.var = 1) + tmp[tmp$value > 0, 1:2] + } > faithful2 <- merge(faithful, fn()) > intrv <- with(intrv, paste(V1, V2, sep = "-")) > faithful2 <- rename(faithful2, c(variable = "erupt")) > faithful2$erupt <- factor(faithful2$erupt, labels = intrv) |
> panel.ls.gg <- function(x, n = 50, ...) { + fit <- logspline(x) + xx <- do.breaks(range(x), n) + yy <- dlogspline(xx, fit) + data.frame(xx, yy, ...) + } > a <- ddply(faithful2, .(erupt), function(df) { + panel.ls.gg(df$waiting) + }) |
> pg <- ggplot(a, aes(xx, yy)) + geom_line() + facet_grid(~erupt) > print(pg) |
Figure 13.4
> data(Chem97, package = "mlmRev") |
lattice
> panel.bwtufte <- function(x, y, coef = 1.5, ...) { + x <- as.numeric(x) + y <- as.numeric(y) + ux <- sort(unique(x)) + blist <<- tapply(y, factor(x, levels = ux), boxplot.stats, + coef = coef, do.out = FALSE) + blist.stats <<- t(sapply(blist, "[[", "stats")) + blist.out <<- lapply(blist, "[[", "out") + panel.points(y = blist.stats[, 3], x = ux, pch = 16, + ...) + panel.segments(x0 = rep(ux, 2), y0 = c(blist.stats[, + 1], blist.stats[, 5]), x1 = rep(ux, 2), y1 = c(blist.stats[, + 2], blist.stats[, 4]), ...) + } |
> pl <- bwplot(gcsescore^2.34 ~ gender | factor(score), + Chem97, panel = panel.bwtufte, layout = c(6, 1), + ylab = "Transformed GCSE score") > print(pl) |
ggplot2
> dt <- ddply(Chem97, .(gender, score), function(df) { + boxplot.stats(df$gcsescore^2.34)$stats + }) |
> pg <- ggplot(dt, aes(x = gender)) + geom_linerange(aes(ymin = V1, + ymax = V2)) + geom_linerange(aes(ymin = V4, ymax = V5)) + + geom_point(aes(y = V3)) + facet_grid(~score) > print(pg) |
Figure 13.5
lattice
> data(Cars93, package = "MASS") > cor.Cars93 <- cor(Cars93[, !sapply(Cars93, is.factor)], + use = "pair") > ord <- order.dendrogram(as.dendrogram(hclust(dist(cor.Cars93)))) > panel.corrgram <- function(x, y, z, subscripts, at, level = 0.9, + label = FALSE, ...) { + require("ellipse", quietly = TRUE) + x <- as.numeric(x)[subscripts] + y <- as.numeric(y)[subscripts] + z <- as.numeric(z)[subscripts] + zcol <- level.colors(z, at = at, ...) + for (i in seq(along = z)) { + ell <- ellipse(z[i], level = level, npoints = 50, + scale = c(0.2, 0.2), centre = c(x[i], y[i])) + panel.polygon(ell, col = zcol[i], border = zcol[i], + ...) + } + if (label) + panel.text(x = x, y = y, lab = 100 * round(z, + 2), cex = 0.8, col = ifelse(z < 0, "white", + "black")) + } |
> pl <- levelplot(cor.Cars93[ord, ord], at = do.breaks(c(-1.01, + 1.01), 20), xlab = NULL, ylab = NULL, colorkey = list(space = "top"), + scales = list(x = list(rot = 90)), panel = panel.corrgram, + label = TRUE) > print(pl) |
ggplot2
Ellipses are not supported in ggplot2. |
Figure 13.6
lattice
> panel.corrgram.2 <- function(x, y, z, subscripts, at = pretty(z), + scale = 0.8, ...) { + require("grid", quietly = TRUE) + x <- as.numeric(x)[subscripts] + y <- as.numeric(y)[subscripts] + z <- as.numeric(z)[subscripts] + zcol <- level.colors(z, at = at, ...) + for (i in seq(along = z)) { + lims <- range(0, z[i]) + tval <- 2 * base::pi * seq(from = lims[1], to = lims[2], + by = 0.01) + grid.polygon(x = x[i] + 0.5 * scale * c(0, sin(tval)), + y = y[i] + 0.5 * scale * c(0, cos(tval)), + default.units = "native", gp = gpar(fill = zcol[i])) + grid.circle(x = x[i], y = y[i], r = 0.5 * scale, + default.units = "native") + } + } |
> pl <- levelplot(cor.Cars93[ord, ord], xlab = NULL, ylab = NULL, + at = do.breaks(c(-1.01, 1.01), 101), panel = panel.corrgram.2, + scales = list(x = list(rot = 90)), colorkey = list(space = "top"), + col.regions = colorRampPalette(c("red", "white", + "blue"))) > print(pl) |
ggplot2
Not supported in +ggplot2+. |
Figure 13.7
lattice
> panel.3d.contour <- function(x, y, z, rot.mat, distance, + nlevels = 20, zlim.scaled, ...) { + add.line <- trellis.par.get("add.line") + panel.3dwire(x, y, z, rot.mat, distance, zlim.scaled = zlim.scaled, + ...) + clines <- contourLines(x, y, matrix(z, nrow = length(x), + byrow = TRUE), nlevels = nlevels) + for (ll in clines) { + m <- ltransform3dto3d(rbind(ll$x, ll$y, zlim.scaled[2]), + rot.mat, distance) + panel.lines(m[1, ], m[2, ], col = add.line$col, + lty = add.line$lty, lwd = add.line$lwd) + } + } |
> pl <- wireframe(volcano, zlim = c(90, 250), nlevels = 10, + aspect = c(61/87, 0.3), panel.aspect = 0.6, panel.3d.wireframe = "panel.3d.contour", + shade = TRUE, screen = list(z = 20, x = -60)) > print(pl) |
ggplot2
ggplot2 currently does not support true 3d surfaces. |
Figure 13.8
lattice
> library("maps") > county.map <- map("county", plot = FALSE, fill = TRUE) |
> data(ancestry, package = "latticeExtra") > ancestry <- subset(ancestry, !duplicated(county)) > rownames(ancestry) <- ancestry$county > freq <- table(ancestry$top) > keep <- names(freq)[freq > 10] > ancestry$mode <- with(ancestry, factor(ifelse(top %in% + keep, top, "Other"))) > modal.ancestry <- ancestry[county.map$names, "mode"] |
> library("RColorBrewer") > colors <- brewer.pal(n = nlevels(ancestry$mode), name = "Pastel1") |
> pl <- xyplot(y ~ x, county.map, aspect = "iso", scales = list(draw = FALSE), + xlab = "", ylab = "", par.settings = list(axis.line = list(col = "transparent")), + col = colors[modal.ancestry], border = NA, panel = panel.polygon, + key = list(text = list(levels(modal.ancestry), adj = 1), + rectangles = list(col = colors), x = 1, y = 0, + corner = c(1, 0))) > print(pl) |
ggplot2
> counties <- map_data("county") > counties$reg <- with(counties, paste(region, subregion, + sep = ",")) > co_anc <- merge(counties, ancestry, by.x = "reg", by.y = "county") > co_anc <- co_anc[order(co_anc$order), ] |
> pg <- ggplot(co_anc, aes(long, lat, fill = mode, group = group)) + + geom_polygon() + scale_fill_brewer("", palette = "Pastel1") > print(pg) |
Figure 13.9
lattice
> rad <- function(x) { + pi * x/180 + } > county.map$xx <- with(county.map, cos(rad(x)) * cos(rad(y))) > county.map$yy <- with(county.map, sin(rad(x)) * cos(rad(y))) > county.map$zz <- with(county.map, sin(rad(y))) > panel.3dpoly <- function(x, y, z, rot.mat = diag(4), + distance, ...) { + m <- ltransform3dto3d(rbind(x, y, z), rot.mat, distance) + panel.polygon(x = m[1, ], y = m[2, ], ...) + } > aspect <- with(county.map, c(diff(range(yy, na.rm = TRUE)), + diff(range(zz, na.rm = TRUE)))/diff(range(xx, na.rm = TRUE))) |
> pl <- cloud(zz ~ xx * yy, county.map, par.box = list(col = "grey"), + aspect = aspect, panel.aspect = 0.6, lwd = 0.01, + panel.3d.cloud = panel.3dpoly, col = colors[modal.ancestry], + screen = list(z = 10, x = -30), key = list(text = list(levels(modal.ancestry), + adj = 1), rectangles = list(col = colors), space = "top", + columns = 4), scales = list(draw = FALSE), zoom = 1.1, + xlab = "", ylab = "", zlab = "") > print(pl) |
ggplot2
ggplot2 currently does not support true 3d surfaces. |
Figure 13.10
> library("latticeExtra") > library("mapproj") > data(USCancerRates) > rng <- with(USCancerRates, range(rate.male, rate.female, + finite = TRUE)) > nbreaks <- 50 > breaks <- exp(do.breaks(log(rng), nbreaks)) > breaks2 <- c(unique(breaks[1 + (0:(nbreaks - 1)%/%10) * + 10]), max(breaks) - 0.1) |
lattice
> pl <- mapplot(rownames(USCancerRates) ~ rate.male + rate.female, + data = USCancerRates, breaks = breaks, map = map("county", + plot = FALSE, fill = TRUE, projection = "tetra"), + scales = list(draw = T), xlab = "", main = "Average yearly deaths due to cancer per 100000") > print(pl) |
ggplot2
> USCancerRates.df <- namerows(USCancerRates, col.name = "reg") > co_cancer <- merge(counties, USCancerRates.df, by = c("reg")) > co_cancer <- co_cancer[order(co_cancer$order), ] > co_cancer.m <- melt(co_cancer, measure.vars = c("rate.male", + "rate.female"), na.rm = TRUE) > co_cancer.m$fill <- with(co_cancer.m, as.numeric(as.character(cut(value, + breaks, labels = comma(breaks[-1]))))) |
> brewer.div <- colorRampPalette(brewer.pal(11, "Spectral")) |
> pg <- ggplot(co_cancer.m, aes(long, lat, group = reg, + fill = fill)) + geom_polygon() + coord_map(projection = "tetra") + + facet_wrap(~variable, ncol = 1) + scale_fill_gradientn("", + colours = brewer.div(nbreaks), trans = "log") + opts(title = "Average yearly deaths due to cancer per 100000") > print(pg) |
To leave a comment for the author, please follow the link and comment on their blog: Learning R.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.