eliocamp / ggnewscale

Multiple Fill, Color and Other Scales in `ggplot2`
https://eliocamp.github.io/ggnewscale/
GNU General Public License v3.0
406 stars 18 forks source link

new_scale_fill doesn't work with #18

Closed efratushava closed 5 years ago

efratushava commented 5 years ago

Hello,

Looking at previous issues, I couldn't find the answer. My code look like this, before adding new_scale_fill():

ggplot(all_data, aes(x=name,y=whole_gene, fill=paste(category,fig_name,colors))) + geom_bar(position=position_dodge(), stat="identity", color="grey15") + facet_grid(.~fig_name,drop = T,scales = "free",space = "free")+ scale_fill_manual(values = colours)+ guides(fill = FALSE)+ and produces:

image

Adding "new_scale_fill(), here: ggplot(all_data, aes(x=name,y=whole_gene, fill=paste(category,fig_name,colors))) + geom_bar(position=position_dodge(), stat="identity", color="grey15") + facet_grid(.~fig_name,drop = T,scales = "free",space = "free")+ scale_fill_manual(values = colours)+ guides(fill = FALSE)+ new_scale_fill()+ geom_bar(aes(x=name,y=value_per_category,fill=rep(c("black","yellow"),45)),stat="identity",position=position_dodge(), color="grey45")

output: image

and I don't understand why...

eliocamp commented 5 years ago

Hi! I don't understand what is the expected result, so I'm not sure what's wrong with the plot. In any case, looking at your code, you might not need ggnewscale at all! So here are some general recommendations that might clarify the issue.

If your issue is that you are trying to draw black and yellow bars, then you need to put the fill parameter outside the aes() specification. (See this section of R for data science). Doing that, you don't need ggnewscale because you are not using a new fill scale.

It's also possible is to use your code and add scale_fill_identity() (for that you do need ggnewscale)

Let me know if it's useful for you and if not, can you post a reproducible example that includes the data? You can use the awesome reprex package for that.

efratushava commented 5 years ago

I'll try to explain: I want to make a plot with a geom bar on geom bar, where the front bar is deviding the background bar into 2 groups, where the front and background color is determined by what I want,

for example, Here is the data:

data <- data.frame(name=c("a","b","c"),background=c(5,10,20),front_half1=c(2,4,17))
data$front_half2 <- data$background-data$front_half1
data <- reshape2::melt(data, measure.vars = c("front_half1","front_half2"),value.name = "value", variable.name = "half")

ggplot(data, aes(x=name,y=background, fill=name))+
  geom_bar(position=position_dodge(), stat="identity", color="grey15") +
scale_fill_manual(values = c("green","black","blue"))

image

As you can see, before adding "scale_fill_new" the data is in color green,black,blue as I determined. Adding scale_fill_new remove the determind color from the background"

data <- data.frame(name=c("a","b","c"),background=c(5,10,20),front_half1=c(2,4,17))
data$front_half2 <- data$background-data$front_half1
data <- reshape2::melt(data, measure.vars = c("front_half1","front_half2"),value.name = "value", variable.name = "half")

ggplot(data, aes(x=name,y=background, fill=name))+
  geom_bar(position=position_dodge(), stat="identity", color="grey15") +
scale_fill_manual(values = c("green","black","blue"))+
   new_scale_fill()+ 
  geom_bar(aes(x=name,y=value,fill=half),stat="identity",position=position_dodge(), color="grey45")

image

Also, I must used "aes" if I want the data in the front bar plot to be divided into 2 groups

Hope it is much understandable!

eliocamp commented 5 years ago

(I edited a bit of the formatting of your post)

Ah, thanks! I think I know what the issue is now. For now, and as a workaround, you can get what you want if you define the fill aesthetic inside the geom_*() call and not in the global ggplot() call:

library(ggplot2)
library(ggnewscale)

data <- data.frame(name=c("a","b","c"),background=c(5,10,20),front_half1=c(2,4,17))
data$front_half2 <- data$background-data$front_half1
data <- reshape2::melt(data, measure.vars = c("front_half1","front_half2"),value.name = "value", variable.name = "half")

ggplot(data, aes(x=name,y=background))+
  geom_bar(position=position_dodge(), stat="identity", color="grey15", aes(fill = name)) +
  scale_fill_manual(values = c("green","black","blue"))

ggplot(data, aes(x=name,y=background))+
  geom_bar(aes(fill = name), position=position_dodge(), stat="identity", color="grey15") +
  scale_fill_manual(values = c("green","black","blue"))+
  new_scale_fill()+ 
  geom_bar(aes(x=name,y=value,fill=half),stat="identity",position=position_dodge(), color="grey45")

Created on 2019-08-27 by the reprex package (v0.3.0)

eliocamp commented 5 years ago

Thanks for finding the bug! It should be fixed now in the latest commit. You can use the workaround I showed above or use your original code.

library(ggplot2)
library(ggnewscale)

data <- data.frame(name=c("a","b","c"),background=c(5,10,20),front_half1=c(2,4,17))
data$front_half2 <- data$background-data$front_half1
data <- reshape2::melt(data, measure.vars = c("front_half1","front_half2"),value.name = "value", variable.name = "half")

ggplot(data, aes(x=name,y=background, fill=name))+
  geom_bar(position=position_dodge(), stat="identity", color="grey15") +
  scale_fill_manual(values = c("green","black","blue"))+
  new_scale_fill()+ 
  geom_bar(aes(x=name,y=value,fill=half),stat="identity",position=position_dodge(), color="grey45")

Created on 2019-08-27 by the reprex package (v0.3.0)

efratushava commented 5 years ago

Thank you for the detailed answer!

And what if I want guide only to the second bar?

Running this: ggplot(data, aes(x=name,y=background))+ geom_bar(aes(fill = name), position=position_dodge(), stat="identity", color="grey15") + scale_fill_manual(values = c("green","black","blue"))+ guides(fill=F)+ new_scale_fill()+ geom_bar(aes(x=name,y=value,fill=half),stat="identity",position=position_dodge(), color="grey45")

leaves me with the guide for geom_bar of the background data, and I want only for the front data, a.k.a the second bar plot.. image

eliocamp commented 5 years ago

Something like this?

library(ggplot2)
library(ggnewscale)

data <- data.frame(name=c("a","b","c"),background=c(5,10,20),front_half1=c(2,4,17))
data$front_half2 <- data$background-data$front_half1
data <- reshape2::melt(data, measure.vars = c("front_half1","front_half2"),value.name = "value", variable.name = "half")

ggplot(data, aes(x=name,y=background)) +
   geom_bar(aes(fill = name), position=position_dodge(), stat="identity", color="grey15") + 
   scale_fill_manual(values = c("green","black","blue"), guide = "none") +   # <- Remove the guide here
   new_scale_fill() + 
   geom_bar(aes(x=name,y=value,fill=half),stat="identity",position=position_dodge(), color="grey45")

Created on 2019-08-27 by the reprex package (v0.3.0)

efratushava commented 5 years ago

Great!