【问题标题】:How do I make a categorical variable on x-axis of ggplot geom_line with multiple groups如何在具有多个组的 ggplot geom_line 的 x 轴上创建分类变量
【发布时间】:2019-11-12 16:58:44
【问题描述】:

我开始了

>df57 <- data.frame(cellType = c("4.57", "4.57", "8.57", "8.57", "8.28.57", "8.28.57"), 
                        ORR = c("PD", "nonPD"),
                        BL = rep(0, each=6), 
                        Treated = c(10, -5, 8, -4, 15, -2))
>df57melt <- melt(df57)
>df57melt

cellType    ORR variable  value
1   4.57    PD      BL      0
2   4.57    nonPD   BL      0
3   8.57    PD      BL      0
4   8.57    nonPD   BL      0
5   8.28.57 PD      BL      0
6   8.28.57 nonPD   BL      0
7   4.57    PD      Treated 10
8   4.57    nonPD   Treated -5
9   8.57    PD      Treated 8
10  8.57    nonPD   Treated -4
11  8.28.57 PD      Treated 15
12  8.28.57 nonPD   Treated -2                        

我想制作一个线图,其中治疗在 x 轴上(BL,Treated),值在 y 轴上(连续)。我想要三种细胞类型(4.57、8.57 和 8.28.57;我想用线条颜色编码),每种都有响应变量(PD 和 nonPD;我想用线条样式编码)。

我绘制了我认为应该起作用的东西:

>ggplot(data=df57melt, aes(x=variable, y = value)) + 
  geom_line(aes(linetype = ORR, color = cellType))

geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?

#so I add group info
>ggplot(data=df57melt, aes(x=variable, y = value, group = cellType)) + 
  geom_line(aes(linetype = ORR, color = cellType))

Error: geom_path: If you are using dotted or dashed lines, colour, size and linetype must be constant over the line

#but if I change from categorical x to continuous x...
>ggplot(data=df57melt, aes(x=as.numeric(variable), y = value)) + 
  geom_line(aes(linetype = ORR, color = cellType))

它给了我想要的东西......但不完全是 如何让它将我的 x 识别为分类?

【问题讨论】:

    标签: r ggplot2 graph


    【解决方案1】:

    使用 group 美学来告诉 ggplot 哪些列组合被视为单独的组。 ggplot 将在给定组内的所有点之间画线。

    默认情况下,使用分类 x 轴,ggplot 会将每个 x 值视为一个单独的组。在这种情况下,数据最终按variableORRcellType 分组,导致每组只有一个值。我们可以通过设置group 美学来覆盖它。我们希望ORRcellType 的每个唯一组合都有一个单独的行,因此我们使用interaction(ORR, cellType) 按这两个变量的每个组合进行分组。

    在下面的代码中,我还使用了 tidyr 包中的 gather 将数据帧转换为长格式,因为 reshape2 是一个不再处于积极开发中的旧包。

    library(tidyverse)
    theme_set(theme_classic())
    
    df57 %>% 
      gather(key, value, BL:Treated) %>% 
      ggplot(aes(x=key, y=value)) + 
        geom_line(aes(linetype = ORR, color = cellType, 
                      group=interaction(ORR, cellType))) +
        scale_x_discrete(expand=c(0.05, 0.05))
    

    这样的替代方案怎么样:

    df57 %>% 
      ggplot(aes(x=cellType, Treated, colour=ORR)) + 
        geom_hline(yintercept=0, colour="grey50", size=0.5) +
        geom_text(aes(label=sprintf("%1.1f", Treated))) +
        geom_text(data=. %>% 
                    arrange(cellType) %>%
                    group_by(ORR) %>% 
                    slice(1) %>% 
                    mutate(Treated=0.5*Treated),
                  aes(label=gsub("nP", "n-P", ORR), x=0.65), hjust=1, fontface="bold") +
        geom_segment(aes(xend=cellType, yend=BL), linetype="11", size=0.3) +
        labs(x="Cell Type", y="Treatment Effect") +
        scale_x_discrete(expand=expand_scale(add=c(1,0.25))) + 
        guides(colour=FALSE) + 
        theme_classic(base_size=15)
    

    如果PDnonPD 都可以是正数(或都是负数),那么你可以这样做:

    df57 <- data.frame(cellType = c("4.57", "4.57", "8.57", "8.57", "8.28.57", "8.28.57"), 
                       ORR = c("PD", "nonPD"),
                       BL = rep(0, each=6), 
                       Treated = c(10, 5, 8, 4, 15, -2))
    
    pd=position_dodge(0.5)
    df57 %>% 
      ggplot(aes(x=cellType, Treated, colour=ORR)) + 
        geom_hline(yintercept=0, colour="grey50", size=0.5) +
        geom_text(aes(label=sprintf("%1.1f", Treated)), 
                  position=pd, show.legend=FALSE) +
        geom_linerange(aes(ymin=BL, ymax=Treated), 
                     linetype="11", size=0.3, position=pd) +
        labs(x="Cell Type", y="Treatment Effect") +
        theme_classic(base_size=15) +
        theme(legend.position="bottom",
              legend.margin=margin(t=-5)) +
        scale_x_discrete(expand=expand_scale(add=c(0.3,0.3))) +
        guides(colour=guide_legend(override.aes=list(linetype="solid", size=4)))
    

    当然你也可以颠倒ORRcellType的角色:

    df57 %>% 
      ggplot(aes(x=ORR, Treated, colour=cellType)) + 
        geom_hline(yintercept=0, colour="grey50", size=0.5) +
        geom_text(aes(label=sprintf("%1.1f", Treated)), 
                  position=pd, show.legend=FALSE) +
        geom_linerange(aes(ymin=BL, ymax=Treated), 
                       linetype="11", size=0.3, position=pd) +
        labs(x="ORR", y="Treatment Effect") +
        theme_classic(base_size=15) +
        theme(legend.position="bottom",
              legend.margin=margin(t=-5)) +
        scale_x_discrete(expand=expand_scale(add=c(0.3,0.3))) +
        guides(colour=guide_legend(override.aes=list(linetype="solid", size=4)))
    

    【讨论】:

    • 您的第一个答案正是我想要的。谢谢!您的第二个答案虽然很漂亮,但不起作用,因为“非 PD”结果并不总是负面的。如果他们是积极的,那么它真的会抛弃审美。
    • 我已经更新了我的答案,以解决PDnonPD 都可以是肯定的情况。
    【解决方案2】:

    我知道这不是真正的答案,但我觉得你正试图强行将线放在不应该的地方。我建议:

    ggplot(data=df57melt) + 
      geom_col(aes(x=as.factor(variable), 
                   y = value,fill = as.factor(cellType),
                   color = ORR,
                   group=cellType),
               position = position_dodge(),size = 2)+
      scale_fill_grey()
    

    【讨论】:

    • 我同意。我最初将单个重复绘制为点图,我认为它的数据更加丰富。然而,我的老板想要这条线路,因为他觉得这对他所展示的人来说更直观。那么强制线是不可能的吗?我见过其他人在 x 轴上有分类变量...
    猜你喜欢
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    相关资源
    最近更新 更多