在R中绘制纵跳测试的平均力-位移曲线及95%置信带
如何在R中绘制纵跳测试的平均力-位移曲线并添加95%置信带
我完全懂你的困扰——这种非线性的循环曲线,普通的多项式平滑根本抓不住它的趋势,核心问题在于每一次跳跃的位移采样点都不统一,没法直接做汇总。别担心,咱们可以通过位移对齐插值的方法解决这个问题,下面是完整的R实现方案:
首先,先把你的示例数据整理成可直接使用的格式:
library(tidyverse) library(zoo) # 用于插值操作 # 你的示例数据 jump_data <- tibble( Athlete = c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2), Jump.Number = c(1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3), Displacement = c(0,-16.6667,-33.3334,-50.0001,-66.6668,-83.3335,-100,-50,62,0,-18.75,-37.5,-56.25,-75,-93.75,-40,60,0,-13.64,-27.28,-40.92,-54.56,-68.2,-81.84,-95.48,-100,-40,59,0,-16.6667,-33.3334,-50.0001,-66.6668,-83.3335,-100,-50,62,0,-18.75,-37.5,-56.25,-75,-93.75,-40,60,0,-13.64,-27.28,-40.92,-54.56,-68.2,-81.84,-95.48,-100,-40,59), Force = c(800,400,50,400,800,1000,1600,1400,0,802,479,49,514,900,1500,1200,0,806,379,46,367,700,1167,1400,1700,2000,1567,0,900,500,90,500,900,1100,1700,1500,0,902,579,139,514,1000,1600,1300,0,906,479,116,467,800,1267,1500,1800,2100,1667,0) )
步骤1:统一位移网格,对齐所有跳跃数据
因为每一次跳跃的位移采样点不一致,我们先定义一个覆盖所有位移范围的统一网格,然后把每一次跳跃的力数据插值到这个网格上:
# 定义统一位移网格:从最小位移到最大位移,步长设为1(可根据需求调整精度) common_displacement <- seq(min(jump_data$Displacement), max(jump_data$Displacement), by = 1) # 对每个运动员的每一次跳跃进行插值对齐 aligned_data <- jump_data %>% group_by(Athlete, Jump.Number) %>% arrange(Displacement) %>% # 先按位移排序,保证插值顺序正确 mutate( # 用线性插值将当前跳跃的Force映射到统一位移网格 interpolated_force = approx(Displacement, Force, xout = common_displacement)$y ) %>% ungroup() %>% # 展开成每个位移点对应一条记录 select(Athlete, Jump.Number, displacement = common_displacement, force = interpolated_force) %>% unnest(c(displacement, force)) %>% drop_na() # 移除插值失败的NA值
步骤2:计算均值和95%置信区间
现在所有跳跃数据都对齐到同一个位移网格了,我们可以轻松计算每个位移点的平均力和95%置信带:
summary_data <- aligned_data %>% group_by(Athlete, displacement) %>% summarise( mean_force = mean(force, na.rm = TRUE), # 计算标准误:标准差除以样本量的平方根 se_force = sd(force, na.rm = TRUE)/sqrt(n()), # 95%置信区间:均值 ± 1.96*标准误 lower_ci = mean_force - 1.96*se_force, upper_ci = mean_force + 1.96*se_force, .groups = "drop" )
步骤3:绘制力-位移曲线和置信带
最后用ggplot绘制曲线,置信带用半透明填充,曲线清晰区分不同运动员:
ggplot(summary_data, aes(x = displacement, y = mean_force, color = factor(Athlete))) + # 先画置信带,放在底层 geom_ribbon(aes(ymin = lower_ci, ymax = upper_ci, fill = factor(Athlete)), alpha = 0.2, color = NA) + # 再画平均曲线 geom_line(linewidth = 1) + # 自定义标签和主题 labs( x = "身体重心位移", y = "力", color = "运动员", fill = "运动员", title = "纵跳测试平均力-位移循环曲线", subtitle = "包含95%置信带" ) + theme_minimal() + # 确保x轴范围匹配统一网格 coord_cartesian(xlim = range(common_displacement))
一些补充说明
- 这里用了线性插值,如果你觉得精度不够,可以换成样条插值(把
approx换成spline),不过线性插值对于运动捕捉数据已经足够稳定 - 置信带的计算用了经典的均值±1.96*标准误,符合95%置信区间的统计要求
- 曲线会自然呈现顺时针循环的形状,因为我们保留了位移的正负方向(向下为负,向上为正)
内容的提问来源于stack exchange,提问作者Matt Jordan
相关产品推荐
相关产品推荐

