6

How do you pipe an object into a specific place in an apply call, that isn't the first input? The magrittr dot placeholder does not seem to work for this.

  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]))  
hokeybot
  • 195
  • 5

2 Answers2

7

You can use {} like below

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

[[2]]
[1] 3.5

[[3]]
[1] 5.5
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
  • Wow. I must have tried every combination of wrapping parts in parentheses except the whole thing... Any insight as to the logic behind this? – hokeybot May 18 '22 at 11:32
  • @hokeybot I think it makes the scope of running dat to the global environment, such that lapply can read it from the global scope – ThomasIsCoding May 19 '22 at 05:22
3

Here are two ways, with the magrittr and native pipes.

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

Created on 2022-05-18 by the reprex package (v2.0.1)

Rui Barradas
  • 70,273
  • 8
  • 34
  • 66
  • 1
    Thank you. Yes, that works, but makes for quite difficult to read code, which is very much not what i want (this is for a package vignette for mostly novice users). Solution by @ThomasIsCoding is a bit more elegant (if unintuitive....) – hokeybot May 18 '22 at 11:39
  • @hokeybot Yes, I agree that this is difficult to read but the problem is to have a pipe into a function, `lapply`, that calls another function, the one where the original data is going to be needed. Hence the anonymous function. – Rui Barradas May 18 '22 at 11:51