dplyr::mutate中调用purrr::map处理列表列时出现异常行为
问题成因与解决思路
核心原因:rowwise 模式下的 mutate 迭代逻辑与整列操作冲突
rowwise()标记的tibble,mutate的执行逻辑是按行迭代:每次仅传入当前行的单个列元素到右侧表达式,而非传入完整的列向量。- 你单独执行
map(test_dset$g_test, proc_gtest)时,是把g_test列的3个行元素全部传入map,迭代对象是行,最终返回长度为3的列表,完全符合预期。 - 但在rowwise的mutate中执行
map(g_test, proc_gtest)时,迭代对象变成了当前行g_test存储的p值向量本身:如果第三行的g_test是长度为0的空向量,map遍历空向量就会返回长度为0的结果,而rowwise mutate要求每行返回长度为1的元素,因此触发长度不匹配的报错。
包裹list()后结构异常的原因
你按照报错提示在外层加list(),只是强制把map返回的结果(不管长度是0、1还是n)封装成长度为1的列表元素,满足mutate的长度要求,但没有解决根本逻辑问题:比如某行g_test是长度为2的p值向量,map会返回长度为2的处理结果列表,外层包list()后就变成了「长度为1的列表,内部嵌套长度为2的子列表」,和你预期的「每行对应单个字符串/NA」的结构完全不符。
正确实现方案
二选一即可:
- 保留rowwise模式,直接调用函数,不需要额外加
map:
test_dset %>% rowwise() %>% mutate(ncbi_filt = proc_gtest(g_test))
rowwise已经完成了按行迭代的工作,每次会把当前行的g_test直接传给proc_gtest,返回单个结果,刚好符合要求。
2. 移除rowwise模式,用普通mutate+map处理整列:
test_dset %>% ungroup() %>% # 先取消rowwise分组 mutate(ncbi_filt = map(g_test, proc_gtest))
这时候map的迭代对象是g_test列的所有行元素,和你单独调用map(test_dset$g_test, proc_gtest)的逻辑完全一致。
内容的提问来源于stack exchange,提问作者Quang Nguyen
相关产品推荐
相关产品推荐

