我有一个加速度计数据的时间序列数据集,我在其上运行了一些峰值检测以识别步态的不同阶段。我正在使用ggplot
将左右腿数据绘制为facet_grid
中的两个方面,现在我想重叠geom_rect
来显示每条腿的步态的不同阶段。我可以添加rect图层确定,但我无法弄清楚如何将左geom_rect
s保留在左腿小平面上,将右geom_rect
s保持在右侧小平面上。例如,在步态周期中,当您的体重位于左腿(左侧的站立阶段)时,右腿向前摆动(右侧的摆动阶段),因此相位时间不同。您可以通过直观地比较左右槽的时间点来看到这一点。
我已经用谷歌搜索了我的方式解决问题,我找不到答案。我发现最接近的是this,但作者在各个方面使用相同的geom_rect
因此它不是我想要的。我附加了一个简化的Rscript,数据为csv
。有人可以给我一些提示来制作这个情节吗?
facet_rects_test.zip (.csv and R Script)
谢谢!
答案 0 :(得分:2)
使用tidyr函数的answer是一个很好的解决方案。当然,您可以使用您已熟悉的reshape2软件包获得所需的结果。
您缺少的关键元素是faceting变量可以从多个数据参数中获取,只要它具有相同的名称和级别即可。下面的函数在您读取数据时使用数据(您可能希望在函数定义首次使用之前将其放在脚本中)。
plotAccelerometerDataWithPhasesSuperimposed <- function(acceldf, phasesdf) {
# melt the rows for column left/right in order to facet_wrap on it
acceldf_melted <- melt(acceldf[, c('time_ms', 'Ly', 'Ry')],
id.vars = 'time_ms')
# make the facet variables identical
phasesdf$variable <- factor(phasesdf$side, levels = c('Left', 'Right'),
labels = c('Ly', 'Ry'))
ggplot(acceldf_melted, aes(x=time_ms, y=value)) +
# Phases
geom_rect(data = phasesdf, inherit.aes = FALSE, aes(
xmin = acceldf$time_ms[swingStart],
xmax = acceldf$time_ms[heelStrike] - 1,
ymin = -Inf, ymax = Inf, fill = "Swing"), colour = NA, alpha = 0.3) +
geom_rect(data = phasesdf, inherit.aes = FALSE, aes(
xmin = acceldf$time_ms[toeOff],
xmax = acceldf$time_ms[swingEnd] - 1,
ymin = -Inf, ymax = Inf, fill = "Pre-swing"), colour = NA, alpha = 0.3) +
geom_rect(data = phasesdf, inherit.aes = FALSE, aes(
xmin = acceldf$time_ms[heelStrike],
xmax = acceldf$time_ms[toeOff] - 1,
ymin = -Inf, ymax = Inf, fill = "Stance"), colour = NA, alpha = 0.3) +
# Lines
facet_grid(variable~., labeller = labeller(
variable = c(Ly = "Left", Ry = "Right"))) +
labs(title = "Gait Phases by Accelerometer", x = "time (ms)",
y = "Sensors Values") +
geom_line() +
scale_fill_manual('Phases',
values = c('firebrick2', 'orange', 'steelblue2'),
guide = guide_legend()) +
guides(colour = FALSE) +
theme(legend.direction = "horizontal", legend.position = "bottom",
strip.text.y = element_text(size=16, colour = "blue"))
}
答案 1 :(得分:1)
我认为这是将数据转化为正确形式的问题。
library(tidyverse)
首先,让gait_cycle
转换为长格式并正确命名。将Ly
和Ry
转换为Left
和Right
并调用分组变量side
以匹配side
中的gaitPoints
列数据框。然后,两个数据帧将具有我们用于分面的相同side
列,确保来自每个数据帧的相应数据被绘制在预期的方面中。 gather
函数将数据框格转换为长格式(tidyr
包中的数据框,用于从melt
取代reshape2
。
gait_cycle_m = gait_cycle %>%
select(-X) %>%
rename(Left=Ly, Right=Ry) %>%
gather(side, value, -time_ms)
现在我们需要正确设置三个步态Phases
以进行绘图。我们想要一个&#34; long&#34;数据框,以便我们可以对geom_rect
进行一次调用,并直接将数据列映射到美学。因此,我们创建了b
(开始)和e
(结束)列,这些列将标记步态周期中每个阶段的开始和结束。然后我们创建一个Phases
列,它将成为fill
美学(也就是说,它将标记每个数据行代表的步态的哪个阶段)。
gaitPoints_new = data.frame(swingStart=gait_cycle$time_ms[gaitPoints$swingStart],
heelStrike=gait_cycle$time_ms[gaitPoints$heelStrike],
toeOff=gait_cycle$time_ms[gaitPoints$toeOff],
swingEnd=gait_cycle$time_ms[gaitPoints$swingEnd],
side=gaitPoints$side)
gaitPoints_new = bind_rows(gaitPoints_new %>% select(b=1,e=2,5) %>% mutate(Phases="Pre-swing"),
gaitPoints_new %>% select(b=2,e=3,5) %>% mutate(Phases="Stance"),
gaitPoints_new %>% select(b=3,e=4,5) %>% mutate(Phases="Swing"))
一旦我们正确设置了数据,该图就相对简单了。在下面的代码中,我们仅在data
语句中输入aes
参数和geom
映射,以便aes
继承没有问题。
ggplot() +
geom_rect(data=gaitPoints_new, aes(xmin=b, xmax=e, ymin=-Inf, max=Inf, fill=Phases), alpha=0.5) +
geom_line(data=gait_cycle_m, aes(x=time_ms, y=value)) +
facet_grid(side ~ .) +
scale_fill_manual(values=c('firebrick2','orange','steelblue2')) +
theme_bw() +
theme(legend.position = "bottom") +
labs(x="Time (ms)", y="Sensor Values")