关于r:当N小时隐藏geom_boxplot()中的盒子和晶须

Hide box and whiskers in geom_boxplot() when N is small

我经常进行箱线图绘制,其中一些类别很小,而其他类别则有大量数据,并与抖动的原始数据点叠加在一起。我正在寻找一种隐藏小类别(N <5)类别的盒子和晶须的可靠方法。目的是使这些小类别使用geom_point()层仅显示原始数据,但是有意义的类别将得到"盒须"处理。在我看来,将geom_boxplot()层中的alpha映射到基于N的因子变量的事情似乎不起作用,因为alpha只控制填充,可能控制geom_boxplot中的异常值,而不是盒子和晶须。

过去,只要我愿意将颜色参数浪费在这个问题上,我就会找到一个可行的解决方案。但是,通常我想将颜色实际用于其他用途,并且将其两次映射会导致粗糙的输出。我想到的另一种混乱的解决方案是使用已删除了小类别的数据子集-该计划的问题在于,当这些类别要受position_dodge()约束时,它将无法正确处理情况(如闪避将""类别太少)。

下面的最小示例。

1
2
3
4
5
6
7
8
9
df <- data.frame(group=factor(sample(c("A","B"), size=110, replace=TRUE)),
                 sex=factor(c(rep("M",50), rep("F", 50), rep("NB", 10))),
                 height=c(rnorm(50, 70, 6), rnorm(50, 63, 6), rnorm(10, 65, 6)))

dfsub <- filter(df, !(sex=="NB" & group=="A"))

ggplot(df, aes(x=group, y=height, colour=sex)) +
  geom_boxplot(data=dfsub) +
  geom_point(position=position_jitterdodge(jitter.width=0.2))


我为您的身高数据做了第二列,其中小样本量组中的值被替换为NA。绘制数据时,将原始高度列用作点的y美观,将具有NA值的新列用于小样的点用作y美学。

要使框线图和点正确对齐,请使用geom_boxplot(position_dodge(preserve ="single"))告诉ggplot为框线图保持恒定的宽度,即使缺少数据也是如此。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
require(tidyverse)

df <- data.frame(group = factor(sample(c("A","B"), size = 110, replace = TRUE)),
                 sex = factor(c(rep("M", 50), rep("F", 50), rep("NB", 10))),
                 height = c(rnorm(50, 70, 6), rnorm(50, 63, 6), rnorm(10, 65, 6)))

n <- df %>% #calculate sample sizes
  group_by(group, sex) %>%
  summarize(n = n())

df <- left_join(df, n) %>% #join sample sizes to df
  #make second height column to use for boxplots: NA values if n is too small
  mutate(boxplot_height = ifelse(n < 5, NA, height))


ggplot(df, aes(x = group, colour = sex)) +
  #use height column that has groups with n < 5 coded as NA to plot boxplots
  geom_boxplot(aes(y = boxplot_height),
               #preserve ="single" maintains constant width of boxes
               position = position_dodge(preserve ="single")) +
  geom_point(aes(y = height), #use all height data as y variable for points
             position = position_jitterdodge(jitter.width = 0.2))

enter image description here


好的,我认为这种方式不一定比您当前的选择更好,但是...您可以将df分解为boxplot和scatterplot的dfs,然后将要从boxplot中删除的数据的值修改为超出范围(例如此处为1000)。然后将两者绘制,最后使用coord_cartesian放大相关部分。

要创建df_box,我们将groupsex分组,然后将具有<5个数据点的组的值更改为1000(这样就不必硬编码要更改的值)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
df <- data.frame(group=factor(sample(c("A","B"), size=110, replace=TRUE)),
                 sex=factor(c(rep("M",50), rep("F", 50), rep("NB", 10))),
                 height=c(rnorm(50, 70, 6), rnorm(50, 63, 6), rnorm(10, 65, 6)))

df_box <- df %>%
    group_by(group, sex) %>%
    mutate(temp = ifelse(n() < 5, 1000, 1)) %>%
    ungroup() %>%
    mutate(height = ifelse(temp == 1000, 1000, height)) %>%
    select(-temp)

ggplot(df, aes(x=group, y=height, colour=sex)) +
    geom_boxplot(data=df_box) +
    geom_point(position=position_jitterdodge(jitter.width=0.2)) +
    coord_cartesian(ylim=c(50,90))

image