求层级数据特定分组归一化的优雅dplyr实现方式
符合dplyr风格的层级数据归一化优化方案
问题背景
我有层级数据,因变量为EucDistance,测量值按dog、spacing、stride分类。需要按以下方式归一化数据:
- 计算每个
dog下特定spacing(如100)对应的EucDistance平均值; - 用该平均值对每个
dog的所有EucDistance测量值做归一化。
现有代码可实现需求,但分为两步且取值方式笨拙,不够符合dplyr风格,希望得到更优方案。
数据示例
> dff X Unnamed..0 dog spacing trial stride dxreal dyreal EucDistance 1 0 0 Adeline 80 1 1 -0.45589009 0.414136003 0.6159094 ...(省略部分数据) 42 50 4 Bailey 80 4 5 1.25466959 -0.326264279 1.2963966
现有实现代码
test <- dff %>% group_by(dog,spacing) %>% mutate(grpMean=mean(EucDistance)) test2 <- test %>% group_by(dog) %>% mutate(normED=EucDistance/.data$grpMean[.data$spacing==100][1])
优化后的dplyr风格实现
以下几种方案均遵循dplyr管道式风格,避免了笨拙的索引取值,逻辑更清晰:
方案一:过滤关联法
先提取每个dog对应spacing=100的均值,再关联回原数据完成归一化:
dff_norm <- dff %>% group_by(dog, spacing) %>% summarise(mean_ed = mean(EucDistance), .groups = "drop_last") %>% filter(spacing == 100) %>% select(dog, mean_ed_100 = mean_ed) %>% left_join(dff, ., by = "dog") %>% mutate(normED = EucDistance / mean_ed_100) %>% select(-mean_ed_100) # 可选:移除临时辅助列
方案二:单管道内部分组计算
在dog分组内直接提取目标均值,无需额外关联操作:
dff_norm <- dff %>% group_by(dog, spacing) %>% mutate(grp_mean = mean(EucDistance)) %>% group_by(dog) %>% mutate( mean_ed_100 = first(grp_mean[spacing == 100]), normED = EucDistance / mean_ed_100 ) %>% ungroup() %>% select(-grp_mean, -mean_ed_100) # 可选:移除临时辅助列
方案三:dplyr 1.1.0+专属优雅写法
利用reframe精准提取分组目标值,再映射到原数据:
mean_ed_100 <- dff %>% filter(spacing == 100) %>% group_by(dog) %>% reframe(mean_ed_100 = mean(EucDistance)) dff_norm <- dff %>% left_join(mean_ed_100, by = "dog") %>% mutate(normED = EucDistance / mean_ed_100) %>% select(-mean_ed_100)
内容的提问来源于stack exchange,提问作者Andrew Spence
相关产品推荐
相关产品推荐

