2

I tried to create two separate legends because I wanted to group my legends differently. However, there is this awkward gap between both legends; I want to close the awkward vertical gap between the two legends (as pictured). How can I go about doing so?

Thank you.

picture here

library(cowplot)

data2 <- tibble::tribble(
  ~Color,    ~Item, ~Count,       ~Year,
  "Blue",    "Bag",     50, "2009-2011",
  "Blue", "Wallet",     60, "2009-2011",
  "Green",  "Shoes",     80, "2009-2011",
  "Green",  "Shirt",     90, "2009-2011",
  "Yellow", "Flower",     20, "2009-2011",
  "Yellow",   "Bees",     30, "2009-2011",
  "Blue",    "Bag",     50, "2009-2012",
  "Blue", "Wallet",     60, "2009-2012",
  "Green",  "Shoes",     90, "2009-2012",
  "Green",  "Shirt",     20, "2009-2012",
  "Yellow", "Flower",     10, "2009-2012",
  "Yellow",   "Bees",      5, "2009-2012"
)

palette1 <- c("#4575B4","#74ADD1","#ABD9E9","#800026","#FC4E2A","#FEB24C")
palette2 <- c("#800026","#FC4E2A","#FEB24C")

data2$Count_final <- with(data2, Count * c(1, -1)[(Color == "Yellow") + 1])


full_plot <- ggplot(data=data2)+ 
    geom_bar(aes(x=Year,y=Count_final,fill=Item),stat="identity",position="identity") +
    scale_y_continuous(labels=abs)+
    scale_fill_manual(values=palette1)+
    theme_bw(base_size=18) +
    ylab("Count")+
    theme(legend.position="none")


Legend1 <- 
    data2 %>%
    filter(Item %in% c("Bag","Wallet","Shoes")) %>%
    ggplot(aes(x=Year,fill=Item))+geom_bar()+
    scale_fill_manual(values=palette1,name="Accessories")

Legend2 <- 
    data2 %>%
    filter(Item %in% c("Shirt","Flower","Bees")) %>%
    ggplot(aes(x=Year,fill=Item))+geom_bar()+
    scale_fill_manual(values=palette2,name="Not Accessories")


plot_grid(
    full_plot
    , plot_grid(
      get_legend(Legend1)
      , get_legend(Legend2)
      , nrow = 2
    )
    , nrow = 1
    , rel_heights = c(1,0)

  )



catlovingtaco
  • 123
  • 10

2 Answers2

2

This may not be exactly what you wanted. You may need to use alternative ways to get the colors you likes. This is just one way to solve your problem. Hope it helps.

library(ggplot2)
library(cowplot)
data2 <- tibble::tribble(
  ~Color,    ~Item, ~Count,       ~Year,
  "Blue",    "Bag",     50, "2009-2011",
  "Blue", "Wallet",     60, "2009-2011",
  "Green",  "Shoes",     80, "2009-2011",
  "Green",  "Shirt",     90, "2009-2011",
  "Yellow", "Flower",     20, "2009-2011",
  "Yellow",   "Bees",     30, "2009-2011",
  "Blue",    "Bag",     50, "2009-2012",
  "Blue", "Wallet",     60, "2009-2012",
  "Green",  "Shoes",     90, "2009-2012",
  "Green",  "Shirt",     20, "2009-2012",
  "Yellow", "Flower",     10, "2009-2012",
  "Yellow",   "Bees",      5, "2009-2012"
)

data2$Count_final <- with(data2, Count * c(1, -1)[(Color == "Yellow") + 1])

data2$Item = factor(data2$Item, 
                    levels=c("Accessories","Bag","Bees", "Flower", " ",
                             "Non-accessories", "Shirt","Shoes","Wallet"))

full_plot <- ggplot(data=data2)+ 
  geom_bar(aes(x=Year,y=Count_final,fill=Item),stat="identity",position="identity") +
  scale_y_continuous(labels=abs)+
  theme_bw(base_size=18) +
  ylab("Count")

full_plot + 
  scale_fill_manual(values=c("white", "#4575B4","#74ADD1","#ABD9E9", 
                             "white","white", "#800026","#FC4E2A","#FEB24C"),
                    drop=FALSE)+
  theme(legend.position="right", 
        legend.title=element_blank())

Created on 2020-01-06 by the reprex package (v0.3.0)

Edit

I thought it would be easier to explain it here to your questions than in the comment box. This approach use a single set of ggplot legend labels. By adding spaces and new labels, it looks like two sets of legends. First, we add 3 new levels to variable term: "Accessories", " ", "Non-accessories". In the following order:

data2$Item = factor(data2$Item, 
                    levels=c("Accessories","Bag","Bees", "Flower", " ",
                             "Non-accessories", "Shirt","Shoes","Wallet"))

Then, in ggplot, assign white spaces for those 3 levels. Because there are no actual values for those levels, they would be dropped by default. So we used drop = FALSE to keep them.

You could find several existing packages are helpful to solve your problems alternatively. I feel this approach is more intuitive.

Zhiqiang Wang
  • 6,206
  • 2
  • 13
  • 27
  • thank you for this! could you elaborate a little more on what drop=FALSE means for the scale_fill_manual? i tried reading up but i'm still not sure. all i understand is that i end up getting the colors i want. – catlovingtaco Jan 07 '20 at 00:50
  • I have removed my previous response here and edited my answer, because of space limit. – Zhiqiang Wang Jan 07 '20 at 03:00
1

Use this plot_grid call:

Leg <- plot_grid(get_legend(Legend1), get_legend(Legend2), nrow = 4, align = "hv")
plot_grid(full_plot, Leg)

screenshot

G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • thank you for this suggestion. hmm, the awkward vertical gap is now gone, but there's still a significant horizontal gap. is there a way to fix that as well? thank you. – catlovingtaco Jan 07 '20 at 00:52
  • Play around with the size of the plot, e.g. `windows(5, 6)` if you are on Windows or the corresponding device if not. There is also `rel_wdiths=` and `rel_heighst=` args available for `plot_grid` that you can play around with. – G. Grothendieck Jan 07 '20 at 01:16
  • @G.Grothendieck: Could you and catlovingtaco please double check your legend labels? They appear to be inconsistent with your data, and different from those in my answer. Of course, I could have been wrong. It would be good to know if that is the case. – Zhiqiang Wang Jan 08 '20 at 01:37
  • The content is all from the question so it is whahtever you defined. The answer only shows how to put them together using cowplot. – G. Grothendieck Jan 08 '20 at 15:20