问题
I have a data frame containing multiple numeric columns and one column with different factors. I'd like to produce a unique image containing the plots of the numeric columns, by factor. I tried the following:
varA <- runif(40)
varB <- runif(40)
varB <- runif(40)
varC <- runif(40)
mainVar <- c(rep('cat', 10), rep('dof', 10), rep('mouse', 10), rep('frog', 10))
plotData <- data.frame(varA, varB, varC, mainVar)
pdf('asd.pdf')
par(mfrow=c(2,2))
by(plotData, plotData$mainVar, function(x){
par(mfrow=c(1,3))
boxplot(x$varA)
boxplot(x$varB)
boxplot(x$varC)
})
dev.off()
It produces a unique pdf, but with a page for every factor.
Instead, I'd like to get something like that (without the red lines):
回答1:
First, both techniques shown here prefer data in a "tall" format. There are several tools that will reshape it for you, I'll use
# library(tidyr)
plotDataTall <- tidyr::gather(plotData, k, v, -mainVar)
head(plotDataTall)
# mainVar k v
# 1 cat varA 0.4023846
# 2 cat varA 0.3406813
# 3 cat varA 0.7990530
# 4 cat varA 0.3706167
# 5 cat varA 0.5986029
# 6 cat varA 0.1626782
Other tools include the reshape2
package or the stats function reshape
, both of which are increasingly less-intuitive to use for first time users.
ggplot2
library(ggplot2)
ggplot(plotDataTall, aes(x = k, y = v)) +
geom_boxplot() +
facet_wrap(~ mainVar, nrow=2) +
theme(axis.title.x = element_blank(),
axis.title.y = element_blank())
Base R
Because you cannot nest uses of par(mfrow=...)
(they replace, not nest), you can stick with the over-arching 2x2 and handling the per-variable boxplots within boxplot. This can be with the wide data:
par(mfrow=c(2,2), mar=c(4,3,3,0.1))
ign <- by(plotData, plotData$mainVar, function(x) {
boxplot(x$varA, x$varB, x$varC, main=x$mainVar[1])
})
or the tall format:
par(mfrow=c(2,2), mar=c(4,3,3,0.1))
ign <- by(plotDataTall, plotDataTall$mainVar, function(x) {
boxplot(v~k, data=x, main=x$mainVar[1])
})
(I took the liberty of adjusting the mar
gins, primarily for a shrunken combined plot here. Not required for production.)
回答2:
As r2evans already points out, I doubt this is possible with the base plot function. Using ggplot2 (part of the tidyverse) you can get a one-page plot using:
library(tidyverse)
plotData %>%
gather(var, y, -mainVar) %>%
ggplot(aes(x = var, y = y)) + geom_boxplot() + facet_wrap(~mainVar)
note that this also uses the pipe operator (dplyr), and gather (tidyr) both part of tidyverse
来源:https://stackoverflow.com/questions/49635233/combine-multiple-plots-generated-using-the-by-r-function-in-one-figure