R语言中for循环内数值筛选及列表命名的技术问题
问题分析与解决方案
错误原因
你的代码核心问题是循环中误用了索引值i作为筛选阈值:循环变量i是1到7的整数,而你实际需要用vals[i]来获取对应位置的阈值。因为数据集里所有value都小于1,所以每次筛选value <= i都会保留全部行,导致列表元素内容一致。
修正方案
方案1:修正原for循环
直接把筛选条件里的i替换为vals[i],并给列表添加对应名称:
subj <- c("A1", "A1", "A2", "A2", "A3", "A3", "A4", "A4", "A5", "A5") var1 <- c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2) value <- c(.73, .2, .51, .45, .18, .43, .62, .02, 0, .11) df <- data.frame(subj, var1, value) vals <- c(0.15, 0.18, 0.19, 0.21, 0.24, 0.33, 0.50) output <- vector("list", length(vals)) for (i in 1:length(vals)) { new_data <- df %>% filter(value <= vals[i]) # 替换为对应阈值 output[[i]] <- new_data } # 给列表元素命名为对应阈值 names(output) <- as.character(vals)
方案2:用tidyverse更简洁实现
利用purrr::map可以避免手动写循环,同时自动生成命名列表:
library(purrr) library(dplyr) subj <- c("A1", "A1", "A2", "A2", "A3", "A3", "A4", "A4", "A5", "A5") var1 <- c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2) value <- c(.73, .2, .51, .45, .18, .43, .62, .02, 0, .11) df <- data.frame(subj, var1, value) vals <- c(0.15, 0.18, 0.19, 0.21, 0.24, 0.33, 0.50) # map遍历每个阈值,set_names设置列表名称 output <- map(vals, ~ df %>% filter(value <= .x)) %>% set_names(as.character(vals))
验证结果
以第一个列表元素output[["0.15"]]为例,会保留value <= 0.15的行:
subj var1 value 1 A4 2 0.02 2 A5 1 0.00 3 A5 2 0.11
后续元素会根据对应阈值筛选出符合条件的行,且列表元素名称与阈值一一对应。
内容的提问来源于stack exchange,提问作者Catherine Laing
相关产品推荐
相关产品推荐

