littleworth
littleworth

Reputation: 5169

How to overlay two geom_bar on top of each other without alpha values

I have the following data frame:

library(tidyverse)

plot_dat <- structure(list(sample_name = c("YY", "XX", "YY", 
"XX"), interaction = c("Foo interaction", "Foo interaction", 
"Bar interaction", "Bar interaction"), percent = c(9.54760559277962, 
1.21705741166346, 58.1631385457859, 13.6359995314219)), row.names = c(NA, 
-4L), .Names = c("sample_name", "interaction", "percent"), class = c("tbl_df", 
"tbl", "data.frame"))

plot_dat
#> # A tibble: 4 x 3
#>   sample_name interaction     percent
#>   <chr>       <chr>             <dbl>
#> 1 YY          Foo interaction    9.55
#> 2 XX          Foo interaction    1.22
#> 3 YY          Bar interaction   58.2 
#> 4 XX          Bar interaction   13.6

What I want to do is to create barplot that overlay one on top of each other. I have this code:

plot_dat$interaction <- factor(plot_dat$interaction, 
                               levels = c("Bar interaction", "Foo interaction") )

p <- ggplot(plot_dat, 
            aes(x = sample_name, y = percent, fill = interaction, 
                color = interaction, alpha = interaction)) +
  geom_bar(stat = "identity", position = "identity") +
  scale_alpha_manual(values = c(0.2, 1))
p

The current plot looks like this:

enter image description here

I want Foo interaction to be on the top of the overlay. Currently, it is not so. Such that I have to use alpha values to lighten the Bar interaction so that Foo become visible.

How can I force Foo to appear on top and keep Bar at the back without using alpha values?

Upvotes: 2

Views: 2154

Answers (2)

Z.Lin
Z.Lin

Reputation: 29095

This has been reported before at geom_bar fill order not maintained with stat='identity'. Hadley's response below (bold added for emphasis):

With stat = "identity", the data is not manipulated in any way, so the bars will appear in the order in the original data frame.

You can try arranging the data frame according to the factor level orders before plotting:

ggplot(plot_dat %>% arrange(interaction), 
       aes(x = sample_name, y = percent, fill = interaction)) + 
  geom_col(position = "identity")

plot

Upvotes: 3

Nick de Silva
Nick de Silva

Reputation: 83

It's not the most efficient answer, but you could pass two filters into your code and plot them separately. Here's my code that works:

library(tidyverse)

plot_dat <- structure(list(sample_name = c("YY", "XX", "YY", "XX"),
                       interaction = c("Foo interaction",
                                       "Foo interaction",
                                       "Bar interaction",
                                       "Bar interaction"),
                       percent = c(9.54760559277962,
                                   1.21705741166346,
                                   58.1631385457859,
                                   13.6359995314219)),
                  row.names = c(NA, -4L),
                  .Names = c("sample_name", "interaction", "percent"),
                  class = c("tbl_df", "tbl", "data.frame"))

plot_dat

plot_dat$interaction <- factor(plot_dat$interaction, levels = c("Foo interaction", "Bar interaction") )


cond1 <- plot_dat$interaction == 'Foo interaction'
cond2 <- plot_dat$interaction == 'Bar interaction'

ggplot(plot_dat[cond2,],
   aes(x=sample_name, y=percent, fill=interaction)) +
  geom_bar(stat='identity') +
  geom_bar(mapping=aes(x=plot_dat$sample_name[cond1],
                   y=plot_dat$percent[cond1],
                   fill=plot_dat$interaction[cond1]),
       stat='identity')

Here's the output of the graph.

Upvotes: 1

Related Questions