SO上有很多类似的问题,但这些问题通常是关于应用简单的summean,或者出于某种其他原因,情况可以在很大程度上简化.在这里,我想复制列表列列表中键下某些列的值.下面是一个最小的例子:

Setup

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)
        )
    )

This works and does what I wish for:

i.e. in the first element of 100, under keys 101 and 102 there are the first values of columns 101 and 102, respectively

tbl2 <-
    tbl %>%
    rowwise %>%
    mutate(
        x = list(x %>% inset2('a', a) %>% inset2('b', b))
    )

然而,假设我们有12个密钥,这意味着12个inset2个呼叫.最好将它们放在一起处理或循环通过它们.我在purrr::reduce上try 了这一点,但是,我找不到访问reduce内的源列的方法:

Iterating the keys and trying to use them as a character index on 100:

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)))

上述错误仅发生在.data中,正如预期的那样,key本身作为字符串存在于函数中.我还try 将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)))

此版本运行时没有错误,但分配了实际符号(ab,.)将其转移到列表中,而不是行中的值:

tbl2 <-
    tbl %>%
    rowwise %>%
    mutate(
        x = list(
            reduce(
                keys,
                function(lst, key) {
                    inset2(lst, key, sym(key))
                },
                .init = x
            )
        )
    )

tbl2$x[[1]]$a
a  # this `a` is a symbol

然后我try 首先解析键,并将值传递给函数,尽管我不确定val下面包含什么.它运行时没有错误,但x中的所有值都将是NULL.我认为这意味着!!!syms(keys)返回NULL,因此reduce2执行零循环,并返回NULL.

tbl2 <-
    tbl %>%
    rowwise %>%
    mutate(
        x = list(
            reduce2(
                keys,
                !!!syms(keys),
                function(lst, key, val) {
                    inset2(lst, key, val)
                },
                .init = x
            )
        )
    )

最后我回到了使用keys作为字符载体并依赖.data的 idea .此外,一次完成整个操作可能更有效,而不是逐键移动元素.所以我try 提取所有元素并将它们移动utils::modifyList:

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.

此时,我找到了一个实际的解决方案,并将其作为答案发布.但我认为这是一个有趣的例子,我想知道是否有人提出了一个我错过的琐碎解决方案(上面所有的东西对我来说似乎太复杂和丑陋了).

推荐答案

这是另一个依赖purrr::transpose()的选项:

library(purrr)
library(dplyr)

tbl |>
  mutate(x = map2(x, transpose(pick(all_of(keys))), ~ c(.x, .y)))

判断相同:

identical(
  tbl %>%
    rowwise %>%
    mutate(
      x = list(x %>% inset2('a', a) %>% inset2('b', b))
    ) |>
    ungroup(),
  tbl |>
    mutate(x = map2(x, transpose(pick(all_of(keys))), ~ c(.x, .y)))
  )
)
[1] TRUE

R相关问答推荐

如果行和列名以相同的开头,将矩阵值设置为0

是否可以 Select 安装不带文档的R包以更有效地存储?

ggplot geom_smooth()用于线性回归虚拟变量-没有回归线

r—绘制相交曲线

R s iml包如何处理语法上无效的因子级别?'

是否可以创建一个ggplot与整洁判断的交互作用

如何自定义3D散点图的图例顺序?

如果某些列全部为NA,则更改列

合并DFS列表并将索引提取为新列

如何删除最后一个可操作对象

`lazy_dt`不支持`dplyr/across`?

`夹心::vcovCL`不等于`AER::tobit`标准错误

基于Key->Value数据帧的基因子集相关性提取

如何计算每12行的平均数?

使用ggplot2中的sec_axis()调整次轴

将多个列合并为一个列的有效方法是什么?

如何判断代码是否在R Markdown(RMD)上下文中交互运行?

将日期列从字符转换为日期得到的结果是NAS

使用dplyr删除具有条件的行

R中的交叉表