如何将含列表列的单行tibble作为未嵌套命名向量传入自定义函数
这里有几个简洁的方案,不用pmap()就能实现你要的效果——在函数内部直接按列名引用得到未嵌套的普通向量:
方案1:函数内部处理单行数据,自动展开列表列
我们可以先把传入的单行tibble转换成命名列表,再提取每个列表列的内部元素(也就是展开成普通向量),之后用with()就能直接按列名调用向量了:
library(tidyverse) foo_tibble <- tibble(varr = list(c("A", "B")), var2 = list(c(1, 2, 3))) foo_func <- function(data) { # 提取每行的列元素(展开列表列),转成命名列表 input_list <- data %>% map(~pluck(., 1)) with(input_list, { print(varr) print(is.list(varr)) # 这里可以写你的自定义操作,比如计算var2的总和 sum(var2) }) } # 调用函数 foo_tibble %>% foo_func() #> [1] "A" "B" #> [1] FALSE #> [1] 6
如果想保持函数用...接收参数的灵活性(兼容管道传参的写法),也可以调整成:
foo_func <- function(...) { input_list <- list(...) %>% as_tibble() %>% map(~pluck(., 1)) with(input_list, { print(varr) print(is.list(varr)) sum(var2) }) } foo_tibble %>% foo_func()
方案2:调用时先展开列元素,再传入函数
如果你的函数是明确指定参数的(比如知道要用到varr和var2),可以先把单行tibble的列元素展开成命名列表,再用do.call()传入函数:
# 定义明确参数的函数 foo_func2 <- function(varr, var2) { print(varr) print(is.list(varr)) sum(var2) } # 调用时处理数据 foo_tibble %>% map(~pluck(., 1)) %>% # 展开每个列的列表元素 do.call(foo_func2, .) #> [1] "A" "B" #> [1] FALSE #> [1] 6
为什么原来的with(...)不行?
你之前的with(..., )写法里,...接收的是整个tibble对象,tibble的列表列本身是以长度为1的列表形式存储的,所以with会直接引用这个列表,而不是里面的向量。而pmap()之所以能工作,是因为它会自动把每行的每个列的内部元素(也就是列表里的向量)提取出来作为参数传递,相当于帮你做了pluck(.,1)的操作。
上面的方案都是手动实现了pmap()针对单行的核心逻辑,但不需要启动遍历行的机制,更适合单行场景的简洁性需求。
内容的提问来源于stack exchange,提问作者lost
相关产品推荐
相关产品推荐

