【问题标题】:How to plot paired means for multiple groups in one line graph?如何在一个折线图中绘制多个组的配对均值?
【发布时间】:2020-07-02 15:29:10
【问题描述】:

我还在学习 R 代码,所以这个问题可能很简单,但我就是想不通。

我想从三个不同时间点采集的问卷中绘制带有置信区间的平均分数:基线时、4 个治疗周期后和 8 个治疗周期后。本问卷包含3个量表;感觉、运动和自主神经。所以我想绘制每个时间点三个不同尺度的平均分数。所以我想要一个折线图,X 轴上有时间点(基线;4 个周期后;8 个周期后),Y 轴上我想要分数,图表必须包含三个不同颜色的线,表示感觉、运动和自主秤。我想用ggplot。

我有一个包含以下列的数据框:

  • ID -> 是患者的 ID(我总共有 60 位患者) 数据框)
  • c0sen -> 基线感觉量表评分
  • c4sen -> 4 个疗程后的感觉量表评分
  • c8sen -> 8 个疗程后的感觉量表评分
  • c0mot -> 基线运动量表得分
  • c4mot -> 4 个治疗周期后的运动量表评分
  • c8mot -> 8 周期治疗后运动量表评分
  • c0aut -> 基线时自主规模得分
  • c4aut -> 4 个治疗周期后的自主神经量表评分
  • c8aut -> 8 个治疗周期后的自主神经量表评分

这就是我想要的:

我希望有人可以帮助我!非常感谢!

【问题讨论】:

    标签: r ggplot2 confidence-interval linegraph


    【解决方案1】:

    这是我使用虚构数据得出的。感谢您分享您的数据结构,但将来最好分享数据本身,这可以通过控制台中的dput(your.data.frame) 完成,然后将输出作为代码复制/粘贴到问题中......或只需使用代码创建一个虚拟集,这就是我在这里所做的。

    虚拟数据

    library(tidyr)
    library(dplyr)
    library(ggplot2)
    
    raw_df <- data.frame(
      id=1:60,
      c0sen=rnorm(60, 7, 0.2),
      c4sen=rnorm(60, 8.5, 0.5),
      c8sen=rnorm(60, 11, 1.2),
      c0mot=rnorm(60, 6, 0.3),
      c4mot=rnorm(60, 7.5, 0.5),
      c8mot=rnorm(60, 9.6, 0.8),
      c0aut=rnorm(60, 3, 0.1),
      c4aut=rnorm(60, 2.9, 0.1),
      c8aut=rnorm(60, 3.5, 0.8)
    )
    

    处理数据

    在继续绘图之前,您需要准备数据集以使用ggplot2 进行绘图。与Tidyverse 中的其他包一样,您应该准备好您的数据以跟随Tidy Data Principles,这就是我将在这里使用tidyrdplyr 包所做的。

    您按原样排列的数据有很多相同的信息分散到我们需要gather() 一起的多个列中,但在每列中还有我们需要separate() 分开的多条信息(时间和类型测量)。

    第一步是将数据收集为“长”格式,其中有一列用于measure(c0aut、c8mot 等),一列用于score,同时保持@ 987654334@专栏。然后我们需要将measure 列分成两列:一列描述time,另一列描述测量的type

    df <- raw_df %>%
      gather(key='measure', value='score', -id) %>%
      separate(col=measure, into=c('c_time','type'), sep=2)
    

    最后,我想修复c_time,只给我号码,我们可以这样做:

    df <- df %>% separate(c_time, into=c('c', 'time'), sep=1) %>%
      select(-c)
    

    现在,应该注意 df$time 实际上是一个字符向量(不是数值)...但这实际上没关系,因为我们希望 ggplot2 将其视为序数因子,而不是一个数值,因为在 x 轴上,我们希望 0、4 和 8 均匀分布。

    绘制数据

    既然你提到这对你来说是新的,我将把情节代码分解成几部分,以便按照创建情节所采取的步骤非常容易。首先,我们从基础开始,我们设置数据框以及自始至终使用的通用美学。请注意,color= 映射到类型,group= 也是如此。这是必要的,以便ggplot2 知道数据也应该根据类型进行分组(而不是将数据集作为一个整体)。这对于我们将要绘制的几何图形非常重要。

    p <- ggplot(df, aes(x=time, y=score, color=type, group=type))
    

    统计数据和几何。 然后,我们通过 3 次调用 stat_summary 在绘图区域上绘制数据,绘制线、误差线和点(按此顺序)。误差线是使用均值 +/- 标准误差(“mean_se”)绘制的,当然也可以使用其他函数。我们还必须用错误栏覆盖color= 美学,因为我们希望它们都是黑色的(而不是根据类型着色),我们必须将shape= 美学添加到点以便我们可以映射它键入以匹配您的情节。

    p <- p + stat_summary(
        geom='line', fun=mean) +
      stat_summary(
        geom='errorbar', fun.data=mean_se,
        color='black', width=0.1) +
      stat_summary(
        geom='point', fun=mean, aes(shape=type))
    

    天平。 对于比例尺,我通过重命名 "0", "4", "8" 轴来设置 x 轴属性,并且我还将扩展设置为不扩展为默认值,因为它看起来更好一些。 scale_colorscale_shape 调用很重要,必须同时更改以保持一致,否则您将失去两个刻度之间的连接,ggplot2 实际上会显示两个单独的刻度。

    type_labels <- c('Autonomic', 'Motor', 'Sensory')
    
    p <- p + scale_x_discrete(
        name=NULL, labels=c('Baseline', '4 weeks', '8 weeks'),
        expand=expansion(mult=0.05)) +
      scale_color_manual(name=NULL, labels=type_labels, values=rainbow(3)) +
      scale_shape_discrete(name=NULL, labels=type_labels)
    

    主题元素。 最后,我设置了主题元素,包括命名、保持theme_bw() 的整体简洁外观以及在图例周围添加框,我将其放置在底部。

    p <- p + labs(
        title='EORTC QLQ-CIPN20',
        y='Symptom Score'
      ) +
      theme_bw() +
      theme(
        legend.position='bottom',
        legend.title=element_blank(),
        legend.background = element_rect(color='black')
      )
    p
    

    这一切都为您提供了以下内容:

    【讨论】:

    • 很高兴看到我不是唯一一个喜欢重新创建数据结构挑战的人!干得好!
    • 非常感谢两位非常明确的指示!我刚刚运行了这段代码,它成功了!
    • 就像我评论艾伦的回答一样,这里的两个解决方案代表了解决您问题的两种基本方法。在我展示的情况下,您保留数据集并使用stat_summaryggplot 绘图结构中进行汇总,而在艾伦的回答中,该方法是在进行一些额外处理之前汇总您的数据,然后绘制汇总数据框。两者都是运行良好的“tidyverse”方法,在这种情况下,这可能只是您对命令的偏好和熟悉程度的问题。
    【解决方案2】:

    在这样的问题中包含您的实际数据总是一个好主意,但以下内容应该与您所拥有的非常接近:

    set.seed(123)
    
    df  <- data.frame(ID    = factor(1:60),
                      c0sen = rbinom(60, 15, 8.8/15),
                      c4sen = rbinom(60, 15, 9.2/15),
                      c8sen = rbinom(60, 15, 10/15),
                      c0mot = rbinom(60, 15, 8.1/15),
                      c4mot = rbinom(60, 15, 8.4/15),
                      c8mot = rbinom(60, 15, 8.6/15),
                      c0aut = rbinom(60, 15, 3/15),
                      c4aut = rbinom(60, 15, 3/15),
                      c8aut = rbinom(60, 15, 3.5/15))
    head(df)
    #>   ID c0sen c4sen c8sen c0mot c4mot c8mot c0aut c4aut c8aut
    #> 1  1    10     8     9     6     8     7     1     3     2
    #> 2  2     7    12    11     9     8    13     2     3     5
    #> 3  3     9    10    11     7    10     7     5     3     3
    #> 4  4     7    10    11     9     8     7     2     2     4
    #> 5  5     6     8    11     8     9     8     2     5     6
    #> 6  6    12     9     6     8     7     9     4     3     2
    

    现在,这只是使用 ggplot 绘图的错误格式。您首先需要将数据转换为长格式,然后对其进行汇总。在这里,我们使用reshape2::melt 将数据整形为适当的列,然后使用来自 dplyr 的summarize 进行汇总:

    library(reshape2)
    library(dplyr)
    
    summary_df <- melt(df) %>% 
      mutate(time = as.numeric(substr(variable, 2, 2))) %>%
      transmute(ID, time, modality = as.factor(substr(variable, 3, 5)), 
                score = value) %>%
      group_by(modality, time) %>%
      summarize(mean = mean(score), 
                upper = mean + 1.96 * sd(score)/sqrt(length(score)),
                lower = mean - 1.96 * sd(score)/sqrt(length(score)))
    

    这给了我们一些可以使用的东西:

    summary_df
    #> # A tibble: 9 x 5
    #> # Groups:   modality [3]
    #>   modality  time  mean upper lower
    #>   <fct>    <dbl> <dbl> <dbl> <dbl>
    #> 1 aut          0  2.93  3.35  2.52
    #> 2 aut          4  2.87  3.25  2.48
    #> 3 aut          8  3.45  3.89  3.01
    #> 4 mot          0  7.95  8.38  7.52
    #> 5 mot          4  8.48  8.99  7.98
    #> 6 mot          8  8.62  9.15  8.09
    #> 7 sen          0  8.7   9.18  8.22
    #> 8 sen          4  9.17  9.63  8.71
    #> 9 sen          8 10.1  10.5   9.70
    

    现在我们使用geom_linegeom_pointgeom_errorbar 的组合进行绘图:

    library(ggplot2)
    
    ggplot(summary_df, aes(x = time, y = mean, colour = modality)) + 
      geom_line(size = 1) + 
      geom_point(aes(shape = modality), size = 3) +
      geom_errorbar(aes(ymin = lower, ymax = upper), width = 0.2, size = 1) +
      theme_classic() +
      scale_color_discrete(labels = c("Autonomic", "Motor", "Sensory")) +
      scale_shape_discrete(labels = c("Autonomic", "Motor", "Sensory")) +
      theme(legend.position = "bottom", text = element_text(size = 12)) +
      labs(x = "Cycles", y = "Symptom score")
    

    给我们想要的结果:

    reprex package (v0.3.0) 于 2020 年 7 月 2 日创建

    【讨论】:

    • 哈哈——你和我都在玩这些类型的问题。实际上代表了解决此问题的两种通用方法:stat_summary 命令或创建摘要数据集! OP 有很多工作要做:)
    猜你喜欢
    • 2019-10-31
    • 1970-01-01
    • 2021-09-28
    • 2016-10-07
    • 1970-01-01
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    • 2020-11-10
    相关资源
    最近更新 更多