How to manually increase spacing between two specific boxes within a grouped box plot in R?

為{幸葍}努か 提交于 2021-01-28 05:33:29

问题


Is there a way to increase the spacing between the yellow and red boxes within this box plot?

set.seed(40)
df <- data.frame(
  Outcome = runif(60), 
  Fruit = rep(1:3, each = 10), 
  Freshness = rep(c(0, 0.5), each = 30), 
  Farm = factor(rep(c("A", "B"), each = 5))
) %>% 
  transform(
  Outcome = Outcome*Fruit+Freshness, 
  Fruit = as.factor(Fruit), 
  Freshness = as.factor(Freshness)
)

ggplot(data = df, aes(Farm, Outcome, col = Freshness, fill = Fruit)) + 
  geom_boxplot() + 
  scale_color_manual(values = c("lightslategrey", "black"), labels = c("Stale", "Fresh")) + 
  scale_fill_manual(values = c("red", "orange", "yellow"), labels = c("Apples", "Oranges", "Bananas"))

I want to increase the spacing (or put a gap) between the "Freshness" color groups within each "Farm" group, but not so much that the boxes would be as separated as the "Farm" groups. That is, I only want to increase the spacing between yellow and red boxes to emphasize the difference between "Freshness" groups.

The "Fruit" groups would still maintain their distance between boxes within the group. That is, the neighboring red, orange, and yellow boxes will remain close together.


回答1:


Here you have a hack:

The following things were done:

  • create new Fruit with values outside of range (negative, in this case)
  • restrict ylim to positive values, as to prevent showing this new fruit in the plot
  • fudge legend to not show this fruit (space still remains same, though)
  • hide legend background to make this empty space in legend not show up
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(ggplot2)
set.seed(40)
df <- data.frame(
  Outcome = runif(60), 
  Fruit = rep(1:3, each = 10), 
  Freshness = rep(c(0, 0.5), each = 30), 
  Farm = factor(rep(c("A", "B"), each = 5))
) %>% 
  transform(
    Outcome = Outcome*Fruit+Freshness, 
    Fruit = as.factor(Fruit), 
    Freshness = as.factor(Freshness)
  )

dfe <- data.frame(
    Outcome = rep(-1,2), 
    Fruit = rep(" ", 2), 
    Freshness = c(0, 0),
    Farm=c("A", "B")
  )

df1 <- rbind(df, dfe) %>% 
  mutate(Fruit = factor(Fruit, levels=unique(Fruit)), 
         Freshness = factor(Freshness, levels=unique(Freshness)))

ggplot(data = df1, aes(Farm, Outcome, col = Freshness, fill = Fruit)) + 
  geom_boxplot(position=position_dodge2(padding=.1)) + 
  scale_color_manual(values = c("lightslategrey", "black"), labels = c("Stale", "Fresh")) + 
  scale_fill_manual(values = c("red", "orange", "yellow", "white"), labels = c("Apples", "Oranges", "Bananas", ""))+
  scale_x_discrete(drop=FALSE) + coord_cartesian(ylim=c(0,max(df1$Outcome)))+
  guides(fill = guide_legend(override.aes = list(size = c(rep(.6, 3), 0), fill = c("red", "orange", "yellow", NA))))+
  theme(legend.key = element_rect(fill = "white"))

Created on 2020-05-26 by the reprex package (v0.3.0)




回答2:


You can modify the spacing between the boxes by adding position=position_dodge(width =...)) to geom_boxplot() and playing around with the width selection until satisfied.

ggplot(data = df, aes(Farm, Outcome, col = Freshness, fill = Fruit)) + 
  geom_boxplot(position=position_dodge(width = 1)) + 
  scale_color_manual(values = c("lightslategrey", "black"), labels = c("Stale", "Fresh")) + 
  scale_fill_manual(values = c("red", "orange", "yellow"), labels = c("Apples", "Oranges", "Bananas"))

Here is the original for comparison. And the modified (with width=1) Increasing the spacing between the categories on the X axis is a different problem and a harder one to solve. One simple workaround is to use a facet with free scales on the X axis.

ggplot(data = df, aes(Farm, Outcome, col = Freshness, fill = Fruit)) + 
    geom_boxplot(position=position_dodge(width = 1)) + 
    scale_color_manual(values = c("lightslategrey", "black"), labels = c("Stale", "Fresh")) + 
    scale_fill_manual(values = c("red", "orange", "yellow"), labels = c("Apples", "Oranges", "Bananas")) +
    facet_wrap(~Farm, ncol = 2, scales = "free_x")




回答3:


In addition to dshkol's answer, you can increase spacing between groups but it is somewhat of a hack. First you need to create dummy data that falls between farm A and B (i.e. AA) and plot that. Because there is no data in the plot there won't be anything on the graph. Next, you need to specify your breaks as A and B so that the dummy AA does not show on the plot. You can adjust the spacing between boxplots by using the position_dodge argument and change the spacing between groups by adjusting the expand parameter. How close together the boxplots appear will also depend on what size image you export to.

# get unique values to set scale_x_discrete labels
farms <- unique(df$Farm)
dfmod <- df

# create dummy row with no data except for Farms
dfmod$Farm <- as.character(dfmod$Farm)
dfmod <- rbind(dfmod, list(NA, NA, NA, 'AA'))


ggplot(data = dfmod, aes(Farm, Outcome, col = Freshness, fill = Fruit)) + 
  geom_boxplot(position=position_dodge(1)) + 
  scale_color_manual(values = c("lightslategrey", "black"), labels = c("Stale", "Fresh")) + 
  scale_fill_manual(values = c("red", "orange", "yellow"), labels = c("Apples", "Oranges", "Bananas")) +
  scale_x_discrete(breaks=farms, expand=c(0,2))



来源:https://stackoverflow.com/questions/62013317/how-to-manually-increase-spacing-between-two-specific-boxes-within-a-grouped-box

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