行方式迭代就像应用purrr一样

问题描述 投票:25回答:3

如何使用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来做。可能(也可能不会)更快。

r apply purrr
3个回答
30
投票

您可以使用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


7
投票

请注意,您在示例中仅使用向量化操作,因此您可以做到:

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


3
投票

您可以自由地为“喜欢”的函数创建一个包装器。

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
© www.soinside.com 2019 - 2024. All rights reserved.