指定图例列

时间:2015-10-27 19:20:10

标签: r ggplot2

是否可以手动指示ggplot图例中每列显示的因子数? 这是一个可重现的例子,展示了我想要做的事情:

#loading libraries
library(ggplot2)

#Creating hypothetical dataframe
services<-data.frame(study=c(0),category=c(0),subcategory=c(0))
services<-services[-1,]
services[1:15,1]<-c(1:15)

services[1:4,2]<-c("Provisioning", "Regulating", "Suporting", "Cultural")
services[5:8,2]<-c("Provisioning", "Regulating", "Suporting", "Cultural")
services[9:10,2]<-c("Provisioning", "Regulating") 
services[11:15,2]<-c("Provisioning", "Regulating", "Suporting", "Cultural", "Provisioning")

services[1:4,3]<-c("Water supply", "Climate regulation", "Soil formation",      "Recreation")
services[5:8,3]<-c("Fisheries", "Water purification", "Habitat", "Recreation")
services[9:10,3]<-c("Water supply", "Flood regulation") 
services[11:15,3]<-c("Agriculture", "Water purification", "Soil formation", "Aesthetics", "Fisheries")

services

 #Manually re-ordering subcategory factors by larger categories and by number of occurences in the df (I am also looking for a better way to do this, as it must exist!!)
table(services$subcategory)
services$subcategory  <- factor(services$subcategory, 
                            levels=c(#Cultural services
                              "Recreation", "Aesthetics",
                              #Provisioning services
                              "Fisheries", "Water supply", "Agriculture",
                              #Regulating services
                              "Water purification", "Climate regulation","Flood regulation",
                              #Supporting services
                              "Soil formation", "Habitat"))


#Creating figure
ggplot(services, aes(category, fill=subcategory)) + geom_bar() + 
theme(legend.position="right") + 
guides(fill=guide_legend(ncol=4, title="Ecosystem Service Sub Categories"))+
 xlab("Ecosystem Service Type") +
 ylab("Number of times each ecosystem service was evaluated") 

The Figure produced by this code

What would like the figure legend to look like instead!

An Even more advanced way I'd love the figure to come out as

尽管有this建议,this有人明白这一点,但他们并没有产生我想要的结果。 几个星期以来我一直在思考这个问题并且花了好几个小时寻找解决方案,因为我反对在电源插座,插画师等手动进行这些调整。无法找到一个好的答案,我&#39 ;现在转向你们!谢谢你的帮助!

2 个答案:

答案 0 :(得分:1)

Ha! While Hadley confirmed that it is not possible natively with ggplot2 (see link in comment) there is a very hack-y way to do it that is limited by maximum number of aesthetics that have associated legends in ggplot2.

What I have done is created four dummy data frames and plotted four different aesthetics features (size, color, alpha, linetype) outside of the print window. You then can override the legend aesthetics to make them look like the fill colors. Turn off the original fill legend and voila!

I know the ordering of the groups and within the groups are not exactly what you wanted, but it should be easy enough to change with factor levels etc.

Original Plot

http://i.stack.imgur.com/LXmeo.png

New Plot

http://i.imgur.com/1HyNdlV.png

Code

#####################
# Original code 
#####################

#loading libraries
library(ggplot2)

#Creating hypothetical dataframe
services<-data.frame(study=c(0),category=c(0),subcategory=c(0))
services<-services[-1,]
services[1:15,1]<-c(1:15)

services[1:4,2]<-c("Provisioning", "Regulating", "Suporting", "Cultural")
services[5:8,2]<-c("Provisioning", "Regulating", "Suporting", "Cultural")
services[9:10,2]<-c("Provisioning", "Regulating") 
services[11:15,2]<-c("Provisioning", "Regulating", "Suporting", "Cultural", "Provisioning")

services[1:4,3]<-c("Water supply", "Climate regulation", "Soil formation",      "Recreation")
services[5:8,3]<-c("Fisheries", "Water purification", "Habitat", "Recreation")
services[9:10,3]<-c("Water supply", "Flood regulation") 
services[11:15,3]<-c("Agriculture", "Water purification", "Soil formation", "Aesthetics", "Fisheries")
services$subcategory  <- factor(services$subcategory, levels=c("Recreation", "Aesthetics","Fisheries", "Water supply", "Agriculture","Water purification", "Climate regulation","Flood regulation","Soil formation", "Habitat"))

#####################
# New code 
#####################

# Create dummy variables 
cultural <- data.frame(Cultural_Services = c("Recreation","Aesthetics"),category = c("Cultural","Cultural"))
provisional <- data.frame(Provisioning_Services = c("Fisheries","Water Supply","Agricultre"), category = c("Provisioning","Provisioning","Provisioning"))
regulating <- data.frame(Regulating_Services = c("Water Purification","Climate Regulation","Flood Regulation"), category = c("Regulating","Regulating","Regulating"))
supporting <- data.frame(Supporting_Services = c("Soil Formation","Soil Formation", "Habitat", "Habitat"), x = c("Regulating","Suporting","Regulating","Suporting"),y=c(-1,-1,-2,-2))

## Create plot
ggplot() + 
## Plot the four dummy layer outside of the intended plotting area  
  geom_point(data = provisional, aes(x = category, y = -1, size = Provisioning_Services)) + 
  geom_point(data = cultural, aes(x = category, y = -1, color = Cultural_Services)) +
  geom_point(data = regulating, aes(x = category, y = -1, alpha = Regulating_Services)) +
  geom_line(data = supporting, aes(x = x, y = y, linetype = Supporting_Services)) +
## Add in your real plot goal  
  geom_bar(data = services, aes(category, fill=subcategory)) +
## Remove the Fill legend  
  scale_fill_hue(guide="none") +
## Override the guide aesthetics to make them look like fill colors  
  guides(size = guide_legend(override.aes = list(colour = c("#A3A500","#39B600","#00BF7D"),fill = c(NA,NA,NA), shape = c(15,15,15), size = c(8,8,8)),title="Provisioning Services"),
         color = guide_legend(override.aes = list(colour = c("#F8766D","#D89000"), shape = c(15,15), size = c(8,8)),title = "Cultural Services"),
         alpha = guide_legend(override.aes = list(colour = c("#00BFC4","#00B0F6","#9590FF"), shape = c(15,15,15),size = c(8,8,8)), title = "Regulating Services"),
         linetype = guide_legend(override.aes = list(colour = c("#E76BF3","#FF62BC"), shape = c(15,15), size = c(8,8)),title = "Supporting Services")) +
## Adjust the plot range to hide all the extra layers  
  ylim(0,5) +
  xlab("Ecosystem Service Type") +
  ylab("Number of times each ecosystem service was evaluated") 
#> Warning: Removed 3 rows containing missing values (geom_point).
#> Warning: Removed 2 rows containing missing values (geom_point).
#> Warning: Removed 3 rows containing missing values (geom_point).
#> geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic?

答案 1 :(得分:1)

今天早上我遇到了类似的问题,并对这个部分解决方案进行了调查。

ggplot(data = services,
       mapping = aes(x = category, fill = interaction(category, subcategory, sep = ', '))) +
  geom_bar() +
  guides(fill = guide_legend(title = 'Category and subcategory'))