如何使用purrr :: map实现行式迭代?
这是我用标准行方式应用的方法。
df <- data.frame(a = 1:10, b = 11:20, c = 21:30)
lst_result <- apply(df, 1, function(x){
var1 <- (x[['a']] + x[['b']])
var2 <- x[['c']]/2
return(data.frame(var1 = var1, var2 = var2))
})
但是,这不是太优雅,我宁愿用purrr来做。可能(也可能不会)更快。
您可以使用pmap
进行逐行迭代。这些列用作您正在使用的任何函数的参数。在您的示例中,您将具有三参数函数。
例如,这里是使用匿名函数的pmap
,用于您正在进行的工作。列按照它们在数据集中的顺序传递给函数。
pmap(df, function(a, b, c) {
data.frame(var1 = a + b,
var2 = c/2)
} )
您可以使用purrr tilde“short-hand”作为匿名函数,方法是按顺序引用列,前面有两个点。
pmap(df, ~data.frame(var1 = ..1 + ..2,
var2 = ..3/2) )
如果您希望将这些特定结果作为data.frame而不是列表,则可以使用pmap_dfr
。
请注意,您在示例中仅使用向量化操作,因此您可以做到:
df %>% dplyr::transmute(var1 = a+b,var2 = c/2)
(或在基地R:transform(df,var1 = a+b,var2 = c/2)[4:5]
)
如果您使用非矢量化函数(如中位数),您可以使用pmap
,如@aosmith的答案,或使用dplyr::rowwise
。
rowwise
速度较慢,包维护者建议使用map
系列,但在某些情况下,它可能比pmap
更容易。当速度不是问题时,我个人仍然使用它:
library(dplyr)
df %>% transmute(var3 = pmap(.,~median(c(..1,..2,..3))))
df %>% rowwise %>% transmute(var3 = median(c(a,b,c)))
(回到严格的未命名列表输出:res %>% split(seq(nrow(.))) %>% unname
)
您可以自由地为“喜欢”的函数创建一个包装器。
rmap <- function (.x, .f, ...) {
if(is.null(dim(.x))) stop("dim(X) must have a positive length")
.x <- t(.x) %>% as.data.frame(.,stringsAsFactors=F)
purrr::map(.x=.x,.f=.f,...)
}
应用新函数rmap
(rowwisemap)
rmap(df1,~{
var1 <- (.x[[1]] + .x[[2]])
var2 <- .x[[3]]/2
return(data.frame(var1 = var1, var2 = var2))
})
附加信息:(从上到下的评估)
df1 <- data.frame(a=1:3,b=1:3,c=1:3)
m <- matrix(1:9,ncol=3)
apply(df1,1,sum)
rmap(df1,sum)
apply(m,1,sum)
rmap(m,sum)
apply(1:10,1,sum) # intentionally throws an error
rmap(1:10,sum) # intentionally throws an error