ggplot2: Top legend key symbol size changes with legend key label

江枫思渺然 提交于 2019-12-19 08:12:50

问题


The Problem

I want to place the legend of my plot above the plot. I also want to place the legend key symbol (colored squares) above the legend key labels (legend text). Unfortunately, when I do this, the legend key symbol "stretches" to fit the size of the label. I imagine ggplot2 is working fine, but how could I manually override this feature?

How do I keep a consistent legend key symbol across the top with labels of variable lengths?

Reproducible Example

(It's not necessarily a minimal example, just in case the structure of my actual code, like the coord_flip and fill calls, has an impact)

library(dplyr)
library(ggplot2)

dataFrame <- diamonds %>%
              group_by(color, cut) %>%
              summarise(count = n()) %>%
              group_by(color) %>%
              mutate(percent = count/sum(count),
                    pretty_label = paste0(round(percent*100, 1), "%")) %>%
              ungroup()

p <- ggplot(data = dataFrame, mapping = aes(x=color, y = percent, group = cut))+
      geom_bar(aes(fill = cut), stat = "identity", position = "fill")+
      geom_text(aes(label = pretty_label), position=position_fill(vjust=0.5), colour="white", stat = "identity")+
      coord_flip()+
      theme(legend.position="top")+
      guides(fill = guide_legend(label.position = "bottom", reverse = TRUE))

plot(p)

Notice how each of the legend symbols are different sizes, depending on the length of the label.

What I have already tried

I imagine it has something to do with guides, but I can't seem to get it right. Using the plot above (p), I have tried the following and more:

  1. From here and here: p + guides(colour = guide_legend(override.aes = list(size=3)))

  2. From here: p + guides(colour = guide_legend(keywidth = .5, keyheight = .5)) and p + guides(colour = guide_legend(keywidth = unit(.5, "cm"), keyheight = unit(.5, "cm")))

  3. From here: (Trying to wrap labels) p + guides(color = guide_legend(nrow = 2))

I've tried other, less "logical" attempts just because. None of which worked.

Final Thoughts

I could just be having a difficult time knowing what to search for. I am always open to figuring out the problem myself, if you are able to point me in the right direction. Any additional resources are more than welcome.

Thanks, in advance!

Session Output

> sessionInfo()
R version 3.5.1 (2018-07-02)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252    LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                           LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] bindrcpp_0.2.2 ggplot2_3.0.0  dplyr_0.7.6   

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.18      bindr_0.1.1       magrittr_1.5      tidyselect_0.2.4  munsell_0.5.0     colorspace_1.3-2  viridisLite_0.3.0
 [8] R6_2.2.2          rlang_0.2.1       plyr_1.8.4        tools_3.5.1       grid_3.5.1        gtable_0.2.0      withr_2.1.2      
[15] yaml_2.1.19       lazyeval_0.2.1    assertthat_0.2.0  digest_0.6.17     tibble_1.4.2      purrr_0.2.5       glue_1.2.0       
[22] labeling_0.3      compiler_3.5.1    pillar_1.2.3      scales_0.5.0      pkgconfig_2.0.1  

回答1:


I don't know if there's a way to control the width of the legend color boxes separately from the text (other than hacking the legend grobs). However, if you add legend.key.width=unit(1.5, "cm") in your theme statement, all of the color boxes will be expanded to the same width (you may have to tweak the 1.5 up or down a bit to get the desired box widths).

library(scales)

ggplot(dataFrame, aes(x=color, y = percent))+
  geom_bar(aes(fill = cut), stat = "identity") +
  geom_text(aes(label = pretty_label), position=position_fill(vjust=0.5), 
            colour="white", size=3)+
  coord_flip()+
  theme(legend.position="top",
        legend.key.width=unit(1.5, "cm"))+
  guides(fill = guide_legend(label.position = "bottom", reverse = TRUE)) +
  scale_y_continuous(labels=percent)

You can save a little space by putting Very Good on two lines:

library(forcats)

ggplot(dataFrame, aes(x=color, y = percent, fill = fct_recode(cut, "Very\nGood"="Very Good")))+
  geom_bar(stat = "identity") +
  geom_text(aes(label = pretty_label), position=position_fill(vjust=0.5), 
            colour="white", size=3)+
  coord_flip()+
  theme(legend.position="top",
        legend.key.width=unit(1.2, "cm"))+
  guides(fill = guide_legend(label.position = "bottom", reverse = TRUE)) +
  labs(fill="Cut") +
  scale_y_continuous(labels=percent)



来源:https://stackoverflow.com/questions/52979035/ggplot2-top-legend-key-symbol-size-changes-with-legend-key-label

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!