SO上有很多类似的问题,但这些问题通常是关于应用简单的sum
或mean
,或者出于某种其他原因,情况可以在很大程度上简化.在这里,我想复制列表列列表中键下某些列的值.下面是一个最小的例子:
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)))
此版本运行时没有错误,但分配了实际符号(a
,b
,.)将其转移到列表中,而不是行中的值:
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.
此时,我找到了一个实际的解决方案,并将其作为答案发布.但我认为这是一个有趣的例子,我想知道是否有人提出了一个我错过的琐碎解决方案(上面所有的东西对我来说似乎太复杂和丑陋了).