如何在tibble列表列中生成含NULL值的组合参数列表?
报错根因
你之前遇到的长度不匹配错误,本质是*ifelse()/dplyr::if_else()这类向量化分支函数存在设计限制*:这类函数要求所有分支的返回值长度严格与判断条件的长度对齐,但NULL是长度为0的特殊R对象,根本无法满足长度对齐要求,因此会直接抛出“replacement has length zero”的报错。
可落地实现方案
方案1:最小改动现有代码,逐行使用标量分支判断
你现有的逻辑已经使用rowwise()逐行处理数据,此时每一行输入的B、m、replace都是长度为1的标量,完全可以直接用R原生的标量if判断替代向量化的ifelse——这种写法没有长度对齐限制,支持正常返回NULL。
修改后的完整可运行代码:
library(tidyverse) # 生成网格序列,包含代表NULL的NA值 B <- seq(from = 50, to = 250, by = 50) m <- c(NA, seq(from = 100, to = 300, by = 100)) replc <- c(TRUE, FALSE) out_crossing <- tidyr::crossing(B, m, replc) %>% dplyr::arrange(B, m) %>% dplyr::rename(replace = replc) %>% dplyr::rowwise() %>% dplyr::mutate( boot_emp = list( tibble::lst( B = B, # 替换原有的ifelse为标量if判断 m = if (!is.na(m)) m else NULL, replace = replace ) ) )
方案2:直接构造列表列,无需逐行计算(大网格下性能更优)
tidyr::crossing()本身支持任意类型的列(包括list类型列),你可以提前把带NULL的m值构造为列表,直接参与交叉连接,完全规避逐行转换的开销,也不需要依赖rowwise计算模式,在网格规模较大时性能提升非常明显。
实现代码:
library(tidyverse) # 提前构造包含NULL的m可选值列表 m_options <- list(100, 200, 300, NULL) out_crossing <- tidyr::crossing( B = seq(from = 50, to = 250, by = 50), m_list = m_options, replace = c(TRUE, FALSE) ) %>% dplyr::mutate( # 为独立列生成可显示的m值:NULL对应展示为NA m = purrr::map_dbl(m_list, ~if (is.null(.x)) NA_real_ else .x), # 直接拼接目标列表列,m_list本身已经是可嵌入list的类型 boot_emp = purrr::pmap( list(B, m_list, replace), ~tibble::lst(B = ..1, m = ..2, replace = ..3) ) )
结果验证
无论使用哪种方案,都可以正常生成包含NULL值的列表列,以m为NULL的行做检查:
# 筛选m为NA(即列表中m为NULL)的行 out_crossing %>% dplyr::filter(is.na(m), B == 50, replace == FALSE) %>% dplyr::pull(boot_emp)
输出结构和预期完全一致:
[[1]] [[1]]$B [1] 50 [[1]]$m NULL [[1]]$replace [1] FALSE
内容的提问来源于stack exchange,提问作者user4687531
相关产品推荐
相关产品推荐

