dplyr按行处理时如何批量将指定列值存入列表列对应键
批量将指定列值合并到列表列的对应键下
Stack Overflow上有不少类似问题,但大多围绕sum、mean这类简单函数展开,场景都能大幅简化。我需要实现的是:将指定列的值批量复制到列表列中对应的键下,以下是最小复现示例:
环境搭建
library(dplyr) library(purrr) library(rlang) library(tibble) library(magrittr) keys <- c('a', 'b') tbl <- tibble( x = list( list(f = 'foo', g = 'bar'), list(f = 'bar', g = 'foo') ), a = list( list(i = 1, j = 2), list(i = 4, j = 7) ), b = list( list(i = 5, j = 3), list(i = 2, j = 9) ) )
单键手动实现(可行但繁琐)
需求是:让x的第一个元素中,键a和b分别对应列a和b的第一个值。手动逐个处理键的代码可以实现:
tbl2 <- tbl %>% rowwise %>% mutate( x = list(x %>% inset2('a', a) %>% inset2('b', b)) )
但如果有12个键,就得调用12次inset2,显然不够高效,我想找到批量处理的方法。
尝试过的批量方法及问题
1. purrr::reduce结合.data pronoun
遍历键并尝试用.data[[key]]索引列,但报错:
tbl2 <- tbl %>% rowwise %>% mutate( x = list( reduce( keys, function(lst, key) { inset2(lst, key, .data[[key]]) }, .init = x ) ) )
错误信息:
Error: object 'key' not found 7: quos(..., .ignore_empty = "all") 6: dplyr_quosures(...) 5: force(dots) 4: mutate_cols(.data, dplyr_quosures(...), by) 3: mutate.data.frame(., x = list(reduce(keys, function(lst, key) { inset2(lst, key, .data[[key]]) }, .init = x))) 2: mutate(., x = list(reduce(keys, function(lst, key) { inset2(lst, key, .data[[key]]) }, .init = x))) 1: tbl %>% rowwise %>% mutate(x = list(reduce(keys, function(lst, key) { inset2(lst, key, .data[[key]]) }, .init = x)))
这里key本身是存在的字符串,但.data无法识别它。
2. 尝试将key转换为符号
把key转成符号后依然报错:
tbl2 <- tbl %>% rowwise %>% mutate( x = list( reduce( keys, function(lst, key) { inset2(lst, key, !!sym(key)) }, .init = x ) ) )
错误信息:
Error: object 'key' not found 9: is_symbol(x) 8: sym(key) 7: quos(..., .ignore_empty = "all") 6: dplyr_quosures(...) 5: force(dots) 4: mutate_cols(.data, dplyr_quosures(...), by) 3: mutate.data.frame(., x = list(reduce(keys, function(lst, key) { inset2(lst, key, !!sym(key)) }, .init = x))) 2: mutate(., x = list(reduce(keys, function(lst, key) { inset2(lst, key, !!sym(key)) }, .init = x))) 1: tbl %>% rowwise %>% mutate(x = list(reduce(keys, function(lst, key) { inset2(lst, key, !!sym(key)) }, .init = x)))
如果去掉!!,代码能运行,但赋值的是符号本身而非对应行的值:
tbl2 <- tbl %>% rowwise %>% mutate( x = list( reduce( keys, function(lst, key) { inset2(lst, key, sym(key)) }, .init = x ) ) ) tbl2$x[[1]]$a # 返回的是符号a,而非对应列的值
3. 使用reduce2传递键和值
尝试用reduce2同时传入键和对应列,但x最终全为NULL,推测!!!syms(keys)没有正确传递值:
tbl2 <- tbl %>% rowwise %>% mutate( x = list( reduce2( keys, !!!syms(keys), function(lst, key, val) { inset2(lst, key, val) }, .init = x ) ) )
4. 使用utils::modifyList批量合并
想一次性提取所有指定列合并到x中,但.data不支持[索引:
tbl2 <- tbl %>% rowwise %>% mutate( x = list(modifyList(x, .data[keys])) )
错误信息:
Error in `mutate()`: ℹ In argument: `x = list(modifyList(x, .data[keys]))`. ℹ In row 1. Caused by error in `.data[keys]`: ! `[` is not supported by the `.data` pronoun, use `[[` or $ instead. Run `rlang::last_trace()` to see where the error occurred.
求助
我已经找到一个可行方案,但总觉得过程太繁琐,想知道有没有更简洁的批量处理方法。
内容的提问来源于stack exchange,提问作者deeenes
相关产品推荐
相关产品推荐

