使用map2_int嵌套case_when时出现长度为0的结果错误
解决按周期和牌照统计罚单数量时的map2_int报错问题
错误原因
当new_data里的某组(var, period)在原data中没有对应记录时,data[data$period == y & data$var == x,]$count会返回长度为0的空向量,但map2_int要求每个迭代必须返回长度为1的整数,这就触发了报错。比如示例里第6条记录是(var=c, period=2),原data中没有这个组合,提取count时得到空向量,导致case_when无法输出合法结果。
推荐:更简洁的tidyverse实现
不用手动构建空的new_data再循环填充,直接用tidyr::complete生成所有可能的period和var组合,再用replace_na补0,代码更高效简洁:
library(tidyverse) data <- tibble( period = c(1,1,1,2,2,3), var = c("a","b","c", "a","b","c"), count = c(2,1,50,1,1,1) ) # 生成所有period和var的组合,空值补0 new_data <- data %>% complete(period = 1:3, var = c("a", "b", "c")) %>% replace_na(list(count = 0))
如果period是连续序列,也可以用full_seq(period, 1)自动识别所有存在的period,不用手动写范围。
修正原map2_int代码的方法
如果一定要保留map2_int的写法,需要确保即使没有匹配结果,也返回长度为1的向量。可以通过以下两种方式处理:
方法1:判断匹配结果长度
new_data$count <- map2_int( new_data$var, new_data$period, \(x, y) { # 提取匹配的count matched <- data %>% filter(period == y, var == x) %>% pull(count) # 空结果返回0,否则返回对应值 if (length(matched) == 0) 0 else matched } )
方法2:用first()确保返回单值
new_data$count <- map2_int( new_data$var, new_data$period, \(x, y) case_when( x %in% filter(data, period == y)$var ~ first(filter(data, period == y & var == x)$count), .default = 0 ) )
内容的提问来源于stack exchange,提问作者r_user_293582
相关产品推荐
相关产品推荐

