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。我很难想出一种方法来可视化这些数据。我想要一个内容丰富的图表:
- 参与者测试分数随时间变化的趋势。
- 随着时间的推移,该趋势与参与者的诊断相比如何
在我的真实数据集中,我有超过 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 名患者可能有点太多了,正如问题的评论中已经提到的那样。这个问题有几种解决方法:
- 汇总数据。
- 创建患者子组并为每个子组绘制图表。
- 过滤掉所有从未生病的患者。
关于最后一个建议,您可以使用以下代码(我从 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)))
然后您可以使用多个分组变量(例如 Month
、neverill
)聚合数据。
注意:第 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)
我们现在可以在一个图中看到:
- 每月的正面分数
- 诊断不足与过度诊断的比例
- 误诊数
>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。我很难想出一种方法来可视化这些数据。我想要一个内容丰富的图表:
- 参与者测试分数随时间变化的趋势。
- 随着时间的推移,该趋势与参与者的诊断相比如何
在我的真实数据集中,我有超过 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 名患者可能有点太多了,正如问题的评论中已经提到的那样。这个问题有几种解决方法:
- 汇总数据。
- 创建患者子组并为每个子组绘制图表。
- 过滤掉所有从未生病的患者。
关于最后一个建议,您可以使用以下代码(我从 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)))
然后您可以使用多个分组变量(例如 Month
、neverill
)聚合数据。
注意:第 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)
我们现在可以在一个图中看到:
- 每月的正面分数
- 诊断不足与过度诊断的比例
- 误诊数