Я прошу прощения, если это излишне с более старыми потоками, обсуждающими достоинства различных механизмов построения графиков в R. Тем не менее, я думаю, что, возможно, стоит показать решения для "простых" многоканальных графиков с тремя основными механизмами построения графиков. Рекомендация @thelatemail об использовании lattice
или ggplot2
для этих типов графиков правильна, и, возможно, этот ответ иллюстрирует почему.
Тем не менее, даже несмотря на то, что для базы R может потребоваться наибольшая настройка через par()
и требуется знакомство с функциями, обнаруженными в library(help = "graphics")
, я склонен использовать базу R для создания показателей качества публикации. В этом PDF .
я нашел отличное обсуждение многопанельной графики с основанием R
Шоном Андерсоном .
Для начала сгенерируйте некоторые воспроизводимые данные ( всегда хорошая идея), состоящие из 18 наборов из 20 пар х-у в одном файле данных с подходящими метками группы и индексом uid
. На графиках будут показаны данные x-y и добавлена сглаживающая линия.
set.seed(1234)
x <- seq(0, 9, length.out = 20)
y <- replicate(6, (x-5) + rnorm(x))
y <- c(y, replicate(6, 5*sin(x) + rnorm(x)))
y <- c(y, replicate(6, 5*atanh((9-x)/10) + rnorm(x)))
a <- gl(3, 120, labels = c("A","B","C")) # these factors are handy
b <- gl(6, 20, length = 360)
uid <- as.numeric(b:a)
df <- data.frame(x, y, a, b, uid)
rm(x, y, a, b, uid) # prevent use of variables outside of the data.frame
По моему опыту, R Studio немного более требовательна к контролю за графиками. Я не уверен, насколько хорошо этот код будет работать в R Studio. С этим предупреждением будет создано графическое устройство соответствующего размера для запуска.
dev.new(width = 6.5, height = 6.5)
Во-первых, решение base R, использующее par(mfrow = c(6, 3)
и параметр внешнего поля (oma
). Это также делает нетипичным использование функции legend()
для добавления заголовков на каждую панель.
par(mfrow = c(6, 3), mar = c(0,0,0,0), oma = c(6, 6, 2, 2))
ylim <- range(df$y) # to ensure uniformly sized plots
ncol <- 3 # number of columns to the plot
for(u in 1:18) {
sel <- df$uid == u
plot(y ~ x, df, subset = sel, ann = FALSE, axes = FALSE, ylim = ylim)
box() # adds a "frame" or "box" around each plot
xy <- loess.smooth(df$x[sel], df$y[sel], span = 1/3)
lines(xy)
if ((u - 1)%%ncol == 0) axis(2, las = 1)
if ((u - 1)%/%ncol == 5) axis(1)
leg.text <- paste(unique(df$a[sel]), unique(df$b[sel]), sep = ":")
legend("top", leg.text, bty = "n")
}
mtext("x", side = 1, outer = TRUE, line = 3)
mtext("y", side = 2, outer = TRUE, line = 3)
И ggplot2
, и lattice
будут возвращать объекты, которые могут быть дополнительно уточнены. Решение с lattice
в этом духе показано здесь.
library(lattice)
o <- xyplot(y ~ x | b:a, df, as.table = TRUE, layout = c(3, 6))
o <- update(o, type = c("p", "smooth"), span = 1/3)
plot(o)
Синтаксис, а также встроенные эстетические принципы отличаются между механизмами построения. Это очевидно в базовом ggplot2
решении.
library(ggplot2)
g <- ggplot(df, aes(x, y)) + geom_point() + facet_wrap(b:a ~ ., ncol = 3)
g <- g + geom_smooth()
plot(g)
Выбор того, какой механизм использовать, является личным. Я упоминал, что я часто предпочитаю базовую графику для точного контроля Для подготовки графиков, отображаемых на мониторе, ggplot2
дает экранные изображения без особых проблем. Для многократного исследования многомерных данных я считаю lattice
наиболее полезным. Это может быть проиллюстрировано временем, необходимым для выполнения кода печати (без загрузки библиотеки). Вывод system.time()
для каждого был получен и показан здесь (с компьютера с Windows i7).
rbind(base = time1, lattice = time2, ggplot = time3)[, 1:3]
> user.self sys.self elapsed
> base 0.05 0.03 0.10
> lattice 0.23 0.03 0.28
> ggplot 1.27 0.05 1.38