R:如何可视化 binary/categorical 数据随时间的变化

R: How to visualize change in binary/categorical data over time

>dput(data)
structure(list(ID = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 
3, 3), Dx = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1), Month = c(0, 
6, 12, 18, 24, 0, 6, 12, 18, 24, 0, 6, 12, 18, 24), score = c(0, 
0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0)), .Names = c("ID", 
"Dx", "Month", "score"), row.names = c(NA, -15L), class = "data.frame")

>data
    ID Dx Month score
1   1  1     0     0
2   1  1     6     0
3   1  1    12     0
4   1  1    18     1
5   1  1    24     1
6   2  1     0     1
7   2  1     6     1
8   2  2    12     1
9   2  2    18     0
10  2  2    24     1
11  3  1     0     0
12  3  1     6     0
13  3  1    12     0
14  3  1    18     0
15  3  1    24     0

假设我有以上data.frame。我有 3 名患者(ID = 1、2 或 3)。 Dx 是诊断(Dx = 1 正常,= 2 患病)。有一个月份变量。最后但并非最不重要的一点是考试分数变量。参与者的测试分数是二进制的,它可以从 0 或 1 变化,也可以从 1 恢复到 0。我很难想出一种方法来可视化这些数据。我想要一个内容丰富的图表:

  1. 参与者测试分数随时间变化的趋势。
  2. 随着时间的推移,该趋势与参与者的诊断相比如何

在我的真实数据集中,我有超过 800 名参与者,所以我不想构建 800 个单独的图表......我认为测试分数变量是二进制的确实让我感到难过。任何帮助将不胜感激。

使用 ggplot2,您可以为每个患者制作带有子图的多面图(请参阅我处理下面大量图的解决方案)。可视化示例:

library(ggplot2)
ggplot(data, aes(x=Month, y=score, color=factor(Dx))) +
  geom_point(size=5) +
  scale_x_continuous(breaks=c(0,6,12,18,24)) +
  scale_color_discrete("Diagnosis",labels=c("normal","diseased")) +
  facet_grid(.~ID) +
  theme_bw()

给出:


在一个图中包括 800 名患者可能有点太多了,正如问题的评论中已经提到的那样。这个问题有几种解决方法:

  1. 汇总数据。
  2. 创建患者子组并为每个子组绘制图表。
  3. 过滤掉所有从未生病的患者。

关于最后一个建议,您可以使用以下代码(我从 an answer 改编自我自己的一个问题):

deleteable <- with(data, ave(Dx, ID, FUN=function(x) all(x==1)))
data2 <- data[deleteable==0,]

您也可以使用它来创建一个新变量来识别生病的患者:

data$neverill <- with(data, ave(Dx, ID, FUN=function(x) all(x==1)))

然后您可以使用多个分组变量(例如 Monthneverill)聚合数据。

注意:第 2 部分需要完成以下大量数据操作。第 1 部分不那么复杂,您可以在下面看到它适合。

使用

library(data.table)
library(ggplot2)
library(reshape2)

比较

首先,将Dx从1到2改成0到1(假设score中的0对应Dx中的1)

data$Dx <- data$Dx - 1

现在,创建一个矩阵,returns 1 表示 1 次诊断和 0 测试,-1 表示 1 次测试和 0 诊断。

compare <- matrix(c(0,1,-1,0),ncol = 2,dimnames = list(c(0,1),c(0,1)))
> compare
  0  1
0 0 -1
1 1  0

现在,让我们对每个事件进行评分。这只是为矩阵中的每个条目查找上面的矩阵:

data$calc <- diag(compare[as.character(data$Dx),as.character(data$score)])

*注意:对于使用匹配的大型矩阵,这可以加快速度,但对于像您这样的较小矩阵,这是一个快速修复

允许我们使用 data.table 聚合:

data <- data.table(data)

现在我们需要创建变量:

tograph <- melt(data[, list(ScoreTrend = sum(score)/.N, 
                            Type = sum(calc)/length(calc[calc != 0]), 
                            Measure = sum(abs(calc))), 
                     by = Month],
                id.vars = c("Month"))
  • ScoreTrend:这会计算每个项目中正分数的比例 月。显示分数随时间变化的趋势
  • 类型:显示随时间变化的 -1 与 1 的比例。如果这个returns-1, 所有事件都是 score = 1,diag = 0。如果它 returns 1,所有事件都是 diag = 1, score = 0。零表示两者之间的平衡
  • 测量:不正确事件的原始数量。

我们将这个数据框沿着月份进行融合,以便我们可以创建一个分面图。

如果没有不正确的事件,我们将得到 Type 的 NaN。要将其设置为 0:

tograph[value == NaN, value := 0]

终于可以画图了

ggplot(tograph, aes(x = Month, y = value)) + geom_line() + facet_wrap(~variable, ncol = 1)

我们现在可以在一个图中看到:

  • 每月的正面分数
  • 诊断不足与过度诊断的比例
  • 误诊数