R函数中filter()报错:Input `..1`需为大小262或1,而非0
问题:处理Target数据时filter函数报错
我有一个大型数据集,包含不同说话者在不同时间点(AOPs)产出的所有词汇,想要为每个说话者的每个时间点生成已知词汇和未知词汇列表。我在R里写了逻辑完全一致的两个函数,分别处理'actual'和'target'数据,只是把变量名里的'actual'换成了'target'。
处理target数据的代码如下:
prepared_data_target <- lapply(AOP_list, FUN = function(element) { data <- target_data %>% filter(data_type == "target" & Speaker == element$Speaker) # 筛选对应说话者 timepoint <- data %>% filter(AOP == element$AOP) # 筛选对应时间点 timepoint <- timepoint$AOP # 提取时间点值 unknown <- data %>% filter(AOP > timepoint) # 筛选所有当前未知词汇 known <- data %>% filter(AOP <= timepoint) # 筛选所有已知词汇 output <- list(timepoint, known, unknown) })
运行这段代码时出现如下错误:
Error: Problem with `filter()` input `..1`. i Input `..1` is `AOP > timepoint`. x Input `..1` must be of size 262 or 1, not size 0.
处理'actual'数据的代码能正常运行,我试过用{{}}包裹过滤变量,但没有解决问题。
问题根源
报错的核心是**AOP_list里存在某个element,其对应的说话者+AOP组合在target_data中没有匹配数据**:
- 执行
timepoint <- data %>% filter(AOP == element$AOP)时,返回空数据框; - 提取
timepoint$AOP后得到长度为0的空向量; - 后续
filter(AOP > timepoint)时,空向量无法和data的262行数据做比较,触发维度不匹配的错误。
而actual_data中不存在这种"说话者+AOP无匹配"的情况,所以代码能正常运行。
修复方案
在代码中加入判断逻辑,提前拦截无匹配的情况,避免后续报错:
prepared_data_target <- lapply(AOP_list, FUN = function(element) { # 筛选当前说话者的所有target数据 data <- target_data %>% filter(data_type == "target" & Speaker == element$Speaker) # 情况1:该说话者无任何target数据 if(nrow(data) == 0){ return(list(timepoint = NA, known = NULL, unknown = NULL)) } # 筛选当前时间点的数据行 timepoint_row <- data %>% filter(AOP == element$AOP) # 情况2:该说话者有数据,但当前时间点无匹配 if(nrow(timepoint_row) == 0){ return(list(timepoint = element$AOP, known = NULL, unknown = NULL)) } # 正常处理流程 timepoint <- timepoint_row$AOP unknown <- data %>% filter(AOP > timepoint) known <- data %>% filter(AOP <= timepoint) # 给输出列表命名,方便后续提取 list(timepoint = timepoint, known = known, unknown = unknown) })
额外优化建议
- 给输出列表命名(如
timepoint、known、unknown),避免后续靠索引取值的混乱; - 提前对
target_data按Speaker和AOP分组预处理,减少lapply中重复筛选的开销:
# 预处理:按说话者+AOP分组,生成命名列表 target_grouped <- target_data %>% filter(data_type == "target") %>% group_by(Speaker, AOP) %>% group_split() %>% setNames(paste0(purrr::map(., ~.$Speaker[1]), "_", purrr::map(., ~.$AOP[1])))
内容的提问来源于stack exchange,提问作者Catherine Laing
相关产品推荐
相关产品推荐

