在R中匹配矩阵内对象与分布列表并采样生成FSA列
为儿童触摸物体数据集添加FSA列的R实现方案
需求说明
现有记录儿童触摸物体的数据集,需为包含bodypart和object列的dataframe新增FSA列,规则如下:
- Animal:从截断正态分布(范围2%-27%)随机采样
- Fabric_Toy、Clothes:从截断对数正态分布随机采样
- Nothing:固定值1
原代码问题分析
你尝试的嵌套循环存在逻辑冗余,多次循环赋值会导致结果被覆盖;且用cbind将列表组合成dist.matrix后,索引结构复杂,易引发错误。
优化实现方案
步骤1:加载依赖包
确保安装并加载提供截断分布函数的truncnorm包:
# 首次运行需安装 # install.packages("truncnorm") library(truncnorm)
步骤2:修正并创建示例数据集
修复原数据中向量长度不匹配的问题:
bodypart <- c("Left_hand", "Left_hand", "Right_hand", "Left_hand", "Right_hand", "Left_hand") object <- c("Animal", "Fabric_Toy", "Nothing", "Fabric_Toy", "Clothes", "Animal") df <- data.frame(bodypart, object)
步骤3:构建清晰的物体-分布映射
用命名列表建立分组与预生成分布的对应关系,结构更直观:
# 预生成各分布的样本集(可按需调整样本量) dist_mapping <- list( Animal = rnormTrunc(100, mean = 0.10, sd = 0.08, min = 0.02, max = 0.27), Fabric = rlnormTrunc(100, meanlog = 0.10, sdlog = 0.08, min = 0, max = Inf), Nothing = rep(1, 100) # 固定值重复生成,统一采样逻辑 ) # 建立物体到分组的映射表 object_group <- data.frame( object = c("Animal", "Fabric_Toy", "Clothes", "Nothing"), group = c("Animal", "Fabric", "Fabric", "Nothing") )
步骤4:生成FSA列(dplyr版本)
用向量化操作替代循环,高效完成匹配与采样:
library(dplyr) df <- df %>% left_join(object_group, by = "object") %>% mutate( FSA = case_when( group == "Animal" ~ sample(dist_mapping$Animal, n(), replace = TRUE), group == "Fabric" ~ sample(dist_mapping$Fabric, n(), replace = TRUE), group == "Nothing" ~ 1, # 直接赋值固定值 TRUE ~ NA_real_ # 处理未匹配的异常物体 ) ) %>% select(-group) # 移除中间分组列
步骤4:生成FSA列(基础R版本)
若不想依赖dplyr,可使用基础R函数实现:
# 匹配分组信息 df$group <- object_group$group[match(df$object, object_group$object)] # 逐行采样生成FSA列 df$FSA <- sapply(df$group, function(g) { if (is.na(g)) return(NA) sample(dist_mapping[[g]], 1) }) # 移除临时分组列 df$group <- NULL
结果示例
运行后df会新增FSA列,每个物体对应正确的采样值:
> df bodypart object FSA 1 Left_hand Animal 0.1123456 2 Left_hand Fabric_Toy 0.9876543 3 Right_hand Nothing 1.0000000 4 Left_hand Fabric_Toy 0.8765432 5 Right_hand Clothes 1.2345679 6 Left_hand Animal 0.0987654
内容的提问来源于stack exchange,提问作者JHo
相关产品推荐
相关产品推荐

