ggplot2:分层图中的填充不准确

时间:2018-08-17 00:09:06

标签: r ggplot2

请考虑以下内容。为什么我无法获得准确的填充和标签?为什么我只能得到一种单色填充?请注意,非循环版本可以完美运行

data(iris)
xx <- list(iris, iris)
xx[[1]]$Sepal.Length <- rnorm(150)
xx[[2]]$Sepal.Length <- rnorm(150,mean = 10)

cols <- c("low" = "#e41a1c", "high"= "#377eb8")
p2 <- p <- ggplot() 
for (i in 1:2) {
  p <- p + geom_histogram(data=xx[[i]], aes(x= Sepal.Length, stat(density), fill= factor(names(cols)[i])))
  p2 <- p2 + geom_histogram(data=xx[[i]], aes(x= Sepal.Length, stat(density), fill= factor(cols[i])))
}
p + scale_fill_manual(values= cols)
p2 + scale_fill_manual(values= cols)

iris <- xx[[1]]
iris2 <- xx[[2]]
p3 <- ggplot() +
  geom_histogram(data= iris, aes(x= Sepal.Length, stat(density), fill= factor("low"))) +
  geom_histogram(data= iris2, aes(x= Sepal.Length, stat(density), fill= factor("high"))) +
  scale_fill_manual(values= cols)
p3

enter image description here enter image description here

enter image description here

2 个答案:

答案 0 :(得分:2)

那不是ggplot的方式。

相反,请考虑执行以下操作

data(iris)
xx <- list(iris, iris)
xx[[1]]$Sepal.Length <- rnorm(150)
xx[[2]]$Sepal.Length <- rnorm(150,mean = 10)

cols <- c("low" = "#e41a1c", "high"= "#377eb8")
names(xx) <- names(cols)

library(tidyverse)
bind_rows(xx, .id = "Key") %>%
    ggplot(aes(Sepal.Length, fill = Key)) +
    geom_histogram()

enter image description here

说明:我们将data.frame中的list行绑定,将list元素的名称存储在Key中。然后,我们只有一个data.frame,并使用fill美学来将不同的Key映射到不同的填充。

答案 1 :(得分:0)

我的假设是调用堆栈的计算延迟。也就是说,将填充映射到"%p"而不评估该表达式。因此,printf("%p\n", a); printf("%p\n", a[0]); 中的映射是相同的。

这最终是正确的。就像@maurits曾经在上面指出的那样,names(cols)[i]并非旨在适应此用例。下面的作品

scale_fill_manual

编辑我们还可以将使用ggplot2(上面建议)的想法与我偏爱# @description Process a set of input data.frame's to extract only the # column of interest and assign a group name dtlist_inputs <- function(dt_list, varname, groups, input= TRUE) { dt_list <- do.call('rbind', (mapply(function(l, groupname, varname) { return(data.frame( group= groupname , var= get(varname, as.environment(l)) )) }, l= dt_list, groupname= groups, varname= varname, SIMPLIFY= FALSE))) return(dt_list) } # @description Histogram for multiple groups, where each group is input as a separate data.frame. # @param dt_list a \code{list} of \code{data.frame}s # @param cols a named vector of colour hexes. # @varname A \code{character} scalar denoting the variable in each element of \code{dt_list} you wish to plot. # @binwidth To be passed to `\code{\link[ggplot2]{geom_histogram}}. # @x_lab To be passed to `\code{\link[ggplot2]{labs}}. # @grouptitle To be passed to `\code{\link[ggplot2]{guides}} for legend label. # @x_breaks To be passed to `\code{\link[ggplot2]{scale_x_continuous}} for axis breaks. GGgroup_histogram <- function(dt_list, cols, varname, binwidth= 0.02, grouptitle= "Error Group", x_lab= "Variable", x_breaks= seq(0,1,.1)) { if (length(dt_list) != length(cols)) stop("length of dt_list and cols must match.") dt_list <- dtlist_inputs(dt_list, varname, groups= names(cols)) sub_title <- paste("Variable:", varname) p <- ggplot() + geom_histogram(data= dt_list, aes(x=var, stat(density), fill= factor(group)), binwidth= binwidth, alpha= 0.5) p <- p + labs(y= "Density", x= x_lab, title= "Distributional differences in relative abs error between groups", subtitle= sub_title) + scale_fill_manual(values= cols) + scale_x_continuous(breaks= x_breaks) + guides(fill= guide_legend(title= grouptitle)) + theme(legend.position = "bottom", axis.title= element_text(face= "bold", size= 11), axis.text= element_text(size= 10), plot.title= element_text(face= "bold.italic", size= 13), plot.subtitle= element_text(face= "bold.italic", size= 12)) return(p) } 的自然倾向进行比较:

dplyr::bind_rows