Search code examples
rpurrr

purrr::pwalk throws error when mutating col while purrr::pmap does not


I'd like to understand why the first block works but the second does not. I believe it has something to do with the fact that pwalk does not actually output anything. However, the error is concated_cols must be size 150 or 1, not 2. I would have expected it to be size 1. What is it outputing?

library(tidyverse)


#pmap: Works
iris|>
  mutate(concated_cols=pmap(
    .l = list(Sepal.Length=Sepal.Length,Petal.Length=Petal.Length),
    .f = \(Sepal.Length,Petal.Length){
      str_c(Sepal.Length,Petal.Length)
    }
  ))


#pwalk: Does not work (in my use case, I was trying to use pwalk to write out files, so this is just to demo the error
iris|>
  mutate(concated_cols=pwalk(
    .l = list(Sepal.Length=Sepal.Length,Petal.Length=Petal.Length),
    .f = \(Sepal.Length,Petal.Length){
      str_c(Sepal.Length,Petal.Length)
    }
  ))

Solution

  • If you read the help for ?purrr::pwalk under the Value section you will find:

    walk() returns the input .x (invisibly). This makes it easy to use in a pipe. The return value of .f() is ignored.

    So your pwalk() is returning list(Sepal.Length=Sepal.Length,Petal.Length=Petal.Length) which is a list of length 2, but your call to mutate() is expecting an object of length 1 or 150.

    Your call to pmap() works because it returns a list of length 150 where each element of the list is an output from your anonymous function.

    pwalk()

    library(purrr)
    library(stringr)
    
    x <- with(
      iris, {
        pwalk(
          .l = list(Sepal.Length=Sepal.Length,Petal.Length=Petal.Length),
          .f = \(Sepal.Length,Petal.Length){
            str_c(Sepal.Length,Petal.Length)
          }
        )
      }
    )
    
    x
    #> $Sepal.Length
    #>   [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1
    #>  [19] 5.7 5.1 5.4 5.1 4.6 5.1 4.8 5.0 5.0 5.2 5.2 4.7 4.8 5.4 5.2 5.5 4.9 5.0
    #> ...
    #> [145] 6.7 6.7 6.3 6.5 6.2 5.9
    #> 
    #> $Petal.Length
    #>   [1] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 1.5 1.6 1.4 1.1 1.2 1.5 1.3 1.4
    #>  [19] 1.7 1.5 1.7 1.5 1.0 1.7 1.9 1.6 1.6 1.5 1.4 1.6 1.6 1.5 1.5 1.4 1.5 1.2
    #> ...
    #> [145] 5.7 5.2 5.0 5.2 5.4 5.1
    

    Same AS

    y <- with(
      iris, {
        list(Sepal.Length=Sepal.Length,Petal.Length=Petal.Length)
      }
    )
    
    y
    #> $Sepal.Length
    #>   [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1
    #>  [19] 5.7 5.1 5.4 5.1 4.6 5.1 4.8 5.0 5.0 5.2 5.2 4.7 4.8 5.4 5.2 5.5 4.9 5.0
    #> ...
    #> [145] 6.7 6.7 6.3 6.5 6.2 5.9
    #> 
    #> $Petal.Length
    #>   [1] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 1.5 1.6 1.4 1.1 1.2 1.5 1.3 1.4
    #>  [19] 1.7 1.5 1.7 1.5 1.0 1.7 1.9 1.6 1.6 1.5 1.4 1.6 1.6 1.5 1.5 1.4 1.5 1.2
    #> ...
    #> [145] 5.7 5.2 5.0 5.2 5.4 5.1
    

    Created on 2024-04-30 with reprex v2.1.0