r - How can I attach a list of custom color palettes to a list of ggplot objects without printing each plot object to the screen? -
i have data frame in r in several of columns factors. i'd create series of bar charts showing relative sizes of each of factor levels. want associate own customized color palettes each of factors, , customize final layout of of bars , legends using gridextra package.
i wrote example script think should achieve that, however, obtained rather surprising result:
library(ggplot2) library(grdevices) library(gridextra) # define dummy data , put in data frame fruit <- factor(c("apple", "orange", "pear", "pear", "pear", "orange", "apple", "apple", "apple", "pear")) cheese <- factor(c("cheddar", "mozarella", "gruyere", "gruyere", "gouda", "parmesan", "gruyere", "gouda", "mozarella", "cheddar")) mydata <- data.frame(fruit, cheese) mydata$dummy <- 0 # define custom color schemes foodclrs <- list() # plot fruit factor in shades of red h <- c(0.0, 0.0, 0.0) s <- c(0.95, 0.85, 0.45) v <- c(0.45, 0.85, 0.95) foodclrs[[1]] <- hsv(h, s, v) # plot cheese factor in shades of green h <- c(0.33, 0.33, 0.33, 0.33, 0.33) s <- c(0.95, 0.93, 0.85, 0.69, 0.45) v <- c(0.45, 0.69, 0.85, 0.93, 0.95) foodclrs[[2]] <- hsv(h, s, v) # create vectors individualized text each plot bsiz=20 fillvars <- c("fruit", "cheese") xlabels <- c("fruits", "cheeses") lgdlabels <- c("types of fruit", "types of cheese") # generate list of plots plots <- list() (ii in 1:2) { plots[[ii]] <- ggplot(data=mydata) + geom_bar(aes_string(x="dummy", fill=fillvars[ii]), position=position_stack(reverse=true)) + scale_fill_manual(values=foodclrs[[ii]], drop=false) + theme_bw(base_size=bsiz) + labs(x=xlabels[ii], y="") + theme(axis.ticks.y=element_blank(), axis.text.y=element_blank()) + guides(fill=guide_legend(title=lgdlabels[ii])) + coord_flip() # print(plots[[ii]]) } # print plots on own custom-shaped grid print(grid.arrange(plots[[1]], plots[[2]], ncol=1, nrow=2))
the output of script looks this:
this not expecting: color palette upper bar chart should have been range of shades of red. seems that, although defined plot object plots[[1]]
have red color palette associated it, when went print it, either r or ggplot2 (i'm not sure which) decided use recent color palette instead; i.e., 1 associated plots[[2]]
.
now here's weird part. if uncomment print statement in for
loop, 2 individual plots rendered in correct color scheme (for brevity, not bother include either of them here), and, more interestingly, combined bar chart object inside grid.arrange()
function displays correct color scheme:
while happy have stumbled across little workaround, i'm curious: why work in first place?
that say, how calling "print" statement @ correct moment inside of for
loop causes color palette become permanently attached each ggplot object, when otherwise not?
what's going on here, "underneath hood", speak? , also, there less kludgy way correct problem? example, there other function call instead of print()
, color palette attach correctly each plot object, without creating bunch of individual "dummy" plots don't need?
ggplot2 isn't scoping. possible workaround wrap things in function, surprised need force(),
f <- function(var, fill, xlab, lab){ force(fill) ggplot(data=mydata) + geom_bar(aes_string(x="dummy", fill=var), position=position_stack(reverse=true)) + scale_fill_manual(values=fill) + theme_bw(base_size=bsiz) + labs(x=xlab, y="") + theme(axis.ticks.y=element_blank(), axis.text.y=element_blank()) + guides(fill=guide_legend(title=lab)) + coord_flip() } pl <- purrr::pmap(.f = f, .l = list(var=fillvars, fill=foodclrs, xlab=xlabels,lab=lgdlabels)) grid.arrange(grobs=pl, nrow=2)
Comments
Post a Comment