在 data.table 中按组绘图
Plotting by group in data.table
我有个人级别的数据,我正在尝试按组动态总结结果。
示例:
set.seed(12039)
DT <- data.table(id = rep(1:100, each = 50),
grp = rep(letters[1:4], each = 1250),
time = rep(1:50, 100),
outcome = rnorm(5000))
我想知道绘制组级摘要的最简单方法,其数据包含在:
DT[ , mean(outcome), by = .(grp, time)]
我想要这样的东西:
dt[ , plot(mean(outcome)), by = .(grp, time)]
但这根本行不通。
我正在使用的可行选项(可以很容易地循环)是:
plot(DT[grp == "a", mean(outcome), by = time])
lines(DT[grp == "b", mean(outcome), by = time])
lines(DT[grp == "c", mean(outcome), by = time])
lines(DT[grp == "d", mean(outcome), by = time])
(添加了颜色等参数,为简洁起见排除)
我觉得这不是最好的方法——考虑到 data.table
处理组的技巧,难道没有更优雅的解决方案吗?
其他来源一直在向我指出 matplot
,但我看不到使用它的直接方法——我是否需要重塑 DT
,是否有一个简单的 [=18] =] 可以完成工作吗?
使用 reshape2,您可以将数据集转换为以下内容:
new_dt <- dcast(dt,time~grp,value.var='outcome',fun.aggregate=mean)
new_dt_molten <- melt(new_dt,id.vars='time')
然后像这样用 ggplot2 绘制它:
ggplot(new_dt_molten,aes(x=time,y=value,colour=variable)) + geom_line()
或者,(实际上更简单的解决方案)您可以直接使用您拥有的数据集并执行以下操作:
ggplot(dt,aes(x=time,y=outcome,colour=grp)) + geom_jitter() + geom_smooth(method='loess')
或
ggplot(dt,aes(x=time,y=outcome,colour=grp)) + geom_smooth(method='loess')
您的方向非常正确。使用 ggplot
执行以下操作:
(dt_agg <- dt[,.(mean = mean(outcome)),by=list(grp,time)]) # Aggregated data.table
grp time mean
1: a 1 0.75865672
2: a 2 0.07244879
---
现在 ggplot 这个汇总 data.table
require(ggplot2)
ggplot(dt_agg, aes(x = time, y = mean, col = grp)) + geom_line()
结果:
Base R 使用 matplot
和 dcast
的解决方案
dt_agg <- dt[ , .(mean = mean(outcome)), by=.(grp,time)]
dt_cast <- dcast(dt_agg, time~grp, value.var="mean")
dt_cast[ , matplot(time, .SD[ , !"time"], type="l", ylab="mean", xlab="")]
# alternative:
dt_cast[ , matplot(time, .SD, type="l", ylab="mean", xlab=""), .SDcols = !"time"]
结果:
有一种方法可以使用 data.table
的 by
参数执行此操作,如下所示:
DT[ , mean(outcome), by = .(grp, time)
][ , {plot(NULL, xlim = range(time),
ylim = range(V1)); .SD}
][ , lines(time, V1, col = .GRP), by = grp]
请注意中间 {...; .SD}
部分是继续链接所必需的。如果 DT[ , mean(outcome), by = .(grp, time)]
已经存储为另一个 data.table
、DT_m
,那么我们可以这样做:
DT_m[ , plot(NULL, xlim = range(time), ylim = range(V1))]
DT_m[ , lines(time, V1, col = .GRP), by = grp]
有输出
可能会出现更奇妙的结果;例如,如果我们想为每个组指定特定的颜色:
grp_col <- c(a = "blue", b = "black",
c = "darkgreen", d = "red")
DT[ , mean(outcome), by = .(grp, time)
][ , {plot(NULL, xlim = range(time),
ylim = range(V1)); .SD}
][ , lines(time, V1, col = grp_col[.BY$grp]), by = grp]
注意
如果将输出发送到 RStudio 图形设备,RStudio 中有一个错误会导致此代码失败。因此,这种方法仅适用于命令行上的 R 或将输出发送到外部设备(我将其发送到 png
以生成上述内容)。
参见 data.table
issue #1524, this RStudio support ticket, and these SO Qs ( and 2)
我有个人级别的数据,我正在尝试按组动态总结结果。
示例:
set.seed(12039)
DT <- data.table(id = rep(1:100, each = 50),
grp = rep(letters[1:4], each = 1250),
time = rep(1:50, 100),
outcome = rnorm(5000))
我想知道绘制组级摘要的最简单方法,其数据包含在:
DT[ , mean(outcome), by = .(grp, time)]
我想要这样的东西:
dt[ , plot(mean(outcome)), by = .(grp, time)]
但这根本行不通。
我正在使用的可行选项(可以很容易地循环)是:
plot(DT[grp == "a", mean(outcome), by = time])
lines(DT[grp == "b", mean(outcome), by = time])
lines(DT[grp == "c", mean(outcome), by = time])
lines(DT[grp == "d", mean(outcome), by = time])
(添加了颜色等参数,为简洁起见排除)
我觉得这不是最好的方法——考虑到 data.table
处理组的技巧,难道没有更优雅的解决方案吗?
其他来源一直在向我指出 matplot
,但我看不到使用它的直接方法——我是否需要重塑 DT
,是否有一个简单的 [=18] =] 可以完成工作吗?
使用 reshape2,您可以将数据集转换为以下内容:
new_dt <- dcast(dt,time~grp,value.var='outcome',fun.aggregate=mean)
new_dt_molten <- melt(new_dt,id.vars='time')
然后像这样用 ggplot2 绘制它:
ggplot(new_dt_molten,aes(x=time,y=value,colour=variable)) + geom_line()
或者,(实际上更简单的解决方案)您可以直接使用您拥有的数据集并执行以下操作:
ggplot(dt,aes(x=time,y=outcome,colour=grp)) + geom_jitter() + geom_smooth(method='loess')
或
ggplot(dt,aes(x=time,y=outcome,colour=grp)) + geom_smooth(method='loess')
您的方向非常正确。使用 ggplot
执行以下操作:
(dt_agg <- dt[,.(mean = mean(outcome)),by=list(grp,time)]) # Aggregated data.table
grp time mean
1: a 1 0.75865672
2: a 2 0.07244879
---
现在 ggplot 这个汇总 data.table
require(ggplot2)
ggplot(dt_agg, aes(x = time, y = mean, col = grp)) + geom_line()
结果:
Base R 使用 matplot
和 dcast
dt_agg <- dt[ , .(mean = mean(outcome)), by=.(grp,time)]
dt_cast <- dcast(dt_agg, time~grp, value.var="mean")
dt_cast[ , matplot(time, .SD[ , !"time"], type="l", ylab="mean", xlab="")]
# alternative:
dt_cast[ , matplot(time, .SD, type="l", ylab="mean", xlab=""), .SDcols = !"time"]
结果:
有一种方法可以使用 data.table
的 by
参数执行此操作,如下所示:
DT[ , mean(outcome), by = .(grp, time)
][ , {plot(NULL, xlim = range(time),
ylim = range(V1)); .SD}
][ , lines(time, V1, col = .GRP), by = grp]
请注意中间 {...; .SD}
部分是继续链接所必需的。如果 DT[ , mean(outcome), by = .(grp, time)]
已经存储为另一个 data.table
、DT_m
,那么我们可以这样做:
DT_m[ , plot(NULL, xlim = range(time), ylim = range(V1))]
DT_m[ , lines(time, V1, col = .GRP), by = grp]
有输出
可能会出现更奇妙的结果;例如,如果我们想为每个组指定特定的颜色:
grp_col <- c(a = "blue", b = "black",
c = "darkgreen", d = "red")
DT[ , mean(outcome), by = .(grp, time)
][ , {plot(NULL, xlim = range(time),
ylim = range(V1)); .SD}
][ , lines(time, V1, col = grp_col[.BY$grp]), by = grp]
注意
如果将输出发送到 RStudio 图形设备,RStudio 中有一个错误会导致此代码失败。因此,这种方法仅适用于命令行上的 R 或将输出发送到外部设备(我将其发送到 png
以生成上述内容)。
参见 data.table
issue #1524, this RStudio support ticket, and these SO Qs (