magrittr管道运算符用于apply函数。

6

如何将一个对象管道传递到apply调用中的特定位置而不是第一个输入? magrittr 的占位符似乎无法解决这个问题。

  dat <- 1:10 
  locs <- list(c(1, 2),
               c(3, 4),
               c(5, 6))
  
  foo <- function(x, y, z) {
    out <- mean(c(x[y], x[z]))
    return(out)
  }
  
  # works
  lapply(locs, function(z) foo(dat, z[1], z[2]))
  
  # none of these work 
  dat %>%
    lapply(locs, function(z) foo(., z[1], z[2]))
    
  dat %>%
    lapply(locs, function(z) foo((.), z[1], z[2]))
    
  dat %>%
    lapply(locs, function(z) {. %>% foo(z[1], z[2])})
    
  
  # New native pipe and placeholder also do not work
  dat |>
    lapply(locs, function(z) foo(_, z[1], z[2]))  
2个回答

6

您可以像下面这样使用{}

>   dat %>%
+     {lapply(locs, function(z) foo(., z[1], z[2]))}
[[1]]
[1] 1.5

[[2]]
[1] 3.5

[[3]]
[1] 5.5

哇,我一定试过了每种括号包裹部分的组合,除了整个表达式本身... 你对这其中的逻辑有什么想法吗? - hokeybot
@hokeybot 我觉得将dat的范围拓展到全局环境,以便lapply可以从全局范围读取它。 - ThomasIsCoding

3

这里有两种方法,一种是使用magrittr管道,另一种是使用原生管道。

suppressPackageStartupMessages(library(magrittr))
dat <- 1:10 
locs <- list(c(1, 2),
             c(3, 4),
             c(5, 6))

foo <- function(x, y, z) {
  out <- mean(c(x[y], x[z]))
  return(out)
}

# wrap the function around parenthesis
dat %>%
  (\(d) lapply(locs, \(z) foo(., z[1], z[2])))()
#> [[1]]
#> [1] 1.5
#> 
#> [[2]]
#> [1] 3.5
#> 
#> [[3]]
#> [1] 5.5

# New native pipe with anonymous function
dat |>
  {\(d) lapply(locs, \(z) foo(x = d, z[1], z[2]))}()
#> [[1]]
#> [1] 1.5
#> 
#> [[2]]
#> [1] 3.5
#> 
#> [[3]]
#> [1] 5.5

此文档由reprex包(v2.0.1)于2022年05月18日创建。


1
谢谢。是的,那个方法可以运行,但会导致代码难以阅读,这与我的初衷大相径庭(因为这是为大多数新手用户准备的软件包文档)。@ThomasIsCoding提供的解决方案更加优雅(尽管有些不直观……) - hokeybot
@hokeybot 是的,我同意这很难读懂,但问题是要将管道传递到一个函数lapply中,该函数调用另一个函数,即需要原始数据的函数。因此使用匿名函数。 - Rui Barradas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接