以编程方式指定scale_fill_manual ggplot调用中的颜色 [英] Programmatically specifying colours in scale_fill_manual ggplot call
问题描述
我想根据特定列中给定的值为ggplot2 facet图的背景着色。使用前面提到的问题的答案,我已经问过,我能够将我需要的东西拼凑在一起。 @ joran回答这个问题特别有用,因为它说明了这种技术创建一个单独的数据框传递给ggplot。
这一切都很好用,给出了如下图所示的输出:
以下是我用于生成上述代码的代码plot:
#用户定义的变量在这里
list_of_names< - c('aa' ,'bb','cc','dd','ee','ff')
list_of_regions< -c('europe','north america','europe','asia','asia ','japan')
#图书馆
要求(ggplot2)
要求(重塑)
#创建无意义的数据列名
set.seed(123)
myrows< - 30
mydf< - data.frame(date = seq(as.Date('2012-01-01 ),by =day,length.out = myrows),
aa = runif(myrows,min = 1,max = 2),
bb = runif(myrows,min = 1,max = 2),
cc = runif(myrows,min = 1,max = 2),
dd = runif(myrows,min = 1,max = 2),
ee = runif(myrows ,min = 1,max = 2),
ff = runif(myrows,min = 1,max = 2))
#将数据帧从宽转换为长
mydf < - melt(mydf,id = c('date'))
mydf $ region < - as.character(unassigned)
#指定区域标签
$ b $ for(ii in seq_along(mydf $ date)){
for(jj in seq_along(list_of_names)){
if(as.character(mydf [ii,2] )==列表名称[jj]){mydf $ region [ii]< - as.character(list_of_regions [jj])}
}
}
#创建数据框(mydf [,c('variable','region')])
mysubset $ value< - median(mydf $ value)#a假娃娃lue,但在数据框中使用的范围之一
mysubset $ date< - as.Date(mydf $ date [1])#在所使用的范围
#内的虚拟日期。 ..和绘图
p1 < - ggplot(mydf,aes(y = value,x = date,group = variable))+
geom_rect(data = mysubset,aes(fill = region) = -Inf,xmax = Inf,ymin = -Inf,ymax = Inf,alpha = 0.3)+
scale_fill_manual(values = c(japan=red,north america=green ())+
geom_line()+
facet_wrap(〜variable,ncol = 2)
print(p1)
我正在使用的真实世界脚本旨在用于许多不同的包含多个不同的数据系列,所以这个脚本将被重复多次,只有变量发生变化。
这使用户定义的元素清晰易于编辑非常重要,这就是为什么 list_of_names
和 list_of_regions
变量放在文件的开头。 (当然,根本不需要更改脚本,而是将这些列表定义为外部文件或将它们作为参数传递给脚本)。我试图通过使用这两个 for
循环来分配区域。我做了一段时间试图用 apply
函数来获得更加以R为中心的解决方案,但无法实现它,所以我放弃了并坚持我所知道的。
然而,在我的代码中, scale_fill_manual
调用需要显式传递变量来定义填充颜色,例如'europe'='蓝色'
。这些变量会根据我正在处理的数据而有所不同,所以对于当前形式的脚本,我需要为每组数据系列手动编辑脚本的ggplot部分。我知道这会很费时,而且我强烈怀疑它也会很容易出错。
Q。理想情况下,我希望能够以编程方式从先前声明的值列表中提取和定义 list_of_regions
)与以前声明的颜色列表相匹配,但我想不出一种方法来实现这一点。您有什么想法吗?
这有帮助吗?
cols < - rainbow(nrow(mtcars))
mtcars $ car <-rownames(mtcars)
ggplot(mtcars, aes(mpg,disp,color = car))+ geom_point()+
scale_colour_manual(limits = mtcars $ car,values = cols)+
guides(color = guide_legend(ncol = 3))
I want to colour the backgrounds of a ggplot2 facet plot depending on the value given in a particular column. Using answers to previous questions I have already asked, I was able to piece what I needed together. @joran's answer to this question was particularly useful as it illustrates the technique of creating a separate data frame to pass to ggplot.
This all works nicely enough, giving the output shown in the following image:
Here is the code I used to generate the above plot:
# User-defined variables go here
list_of_names <- c('aa','bb','cc','dd','ee','ff')
list_of_regions <- c('europe','north america','europe','asia','asia','japan')
# Libraries
require(ggplot2)
require(reshape)
# Create random data with meaningless column names
set.seed(123)
myrows <- 30
mydf <- data.frame(date = seq(as.Date('2012-01-01'), by = "day", length.out = myrows),
aa = runif(myrows, min=1, max=2),
bb = runif(myrows, min=1, max=2),
cc = runif(myrows, min=1, max=2),
dd = runif(myrows, min=1, max=2),
ee = runif(myrows, min=1, max=2),
ff = runif(myrows, min=1, max=2))
# Transform data frame from wide to long
mydf <- melt(mydf, id = c('date'))
mydf$region <- as.character("unassigned")
# Assign regional label
for (ii in seq_along(mydf$date)) {
for (jj in seq_along(list_of_names)) {
if(as.character(mydf[ii,2]) == list_of_names[jj]) {mydf$region[ii] <- as.character(list_of_regions[jj])}
}
}
# Create data frame to pass to ggplot for facet colours
mysubset <- unique(mydf[,c('variable','region')])
mysubset$value <- median(mydf$value) # a dummy value but one within the range used in the data frame
mysubset$date <- as.Date(mydf$date[1]) # a dummy date within the range used
# ... And plot
p1 <- ggplot(mydf, aes(y = value, x = date, group = variable)) +
geom_rect(data = mysubset, aes(fill = region), xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, alpha = 0.3) +
scale_fill_manual(values = c("japan" = "red", "north america" = "green", "asia" = "orange", "europe" = "blue")) +
geom_line() +
facet_wrap( ~ variable, ncol = 2)
print (p1)
The real-world script towards which I am working is intended to be used for many different groups containing many different data series, so this script will be duplicated many times, with only the variables changing.
This makes it important to have the user-defined elements clearly accessible for editing, which is why the list_of_names
and list_of_regions
variables are put right at the start of the file. (Of course, it would be better not to need to change the script at all but rather define these lists as external files or pass them to the script as arguments.) I tried to generalise the solution by using those two for
loops to assign the regions. I did fiddle around for a while trying to get a more R-centric solution using apply
functions but couldn't get it to work so I gave up and stuck with what I knew.
However, in my code as it stands the scale_fill_manual
call needs to be explicitly passed variables to define fill colours, such as 'europe' = 'blue'
. These variables will vary depending on the data I am processing, so with the script in its current form, I will need to manually edit the ggplot part of the script for each group of data series. I know that would be be time-consuming and I strongly suspect it would also be very prone to errors.
Q. Ideally I would like to be able to programmatically extract and define the required values for the scale_fill_manual
call from a previously declared list of values (in this case from list_of_regions
) matched to a previously declared list of colours, but I can't think of a way to achieve this. Do you have any ideas?
Does this help?
cols <- rainbow(nrow(mtcars))
mtcars$car <- rownames(mtcars)
ggplot(mtcars, aes(mpg, disp, colour = car)) + geom_point() +
scale_colour_manual(limits = mtcars$car, values = cols) +
guides(colour = guide_legend(ncol = 3))
这篇关于以编程方式指定scale_fill_manual ggplot调用中的颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!