3

I want to use mutate on each of two data frames in a list, adding a column z = 3 to the first and z = 4 to the second (and returning a list of two data frames).

dfs <- list(data.frame(x = 1), data.frame(y = 2))
mapply(dplyr::mutate, dfs, z = 3:4, SIMPLIFY = FALSE)
#> Error in lazyeval::lazy_dots(...): Promise has already been forced

What's going wrong for me, and how should I go about doing what I want to do?

Rory Nolan
  • 972
  • 10
  • 15

2 Answers2

2

Using an anonymous function works:

mapply(function(df, z) mutate_(df, z=z), dfs, 3:4, SIMPLIFY=FALSE)
#[[1]]
#  x z
#1 1 3
#
#[[2]]
#  y z
#1 2 4
Hong Ooi
  • 56,353
  • 13
  • 134
  • 187
  • Thanks, that does what I want. Any idea why what I tried is failing? – Rory Nolan Dec 22 '16 at 14:44
  • Or without anonymous `Map(mutate_, dfs, z = 3:4)` – akrun Dec 22 '16 at 14:47
  • 2
    @RoryNolan Just changing your original code to use `mutate_` (the "programming friendly" version) works fine. The anonymous function is unnecessary. `mapply(dplyr::mutate_, dfs, z = 3:4, SIMPLIFY = FALSE)`. We could talk about NSE, lazy evaluation, etc as well. – Michael Griffiths Dec 22 '16 at 14:48
1

You could also do this with map2 from the purrr package if you want to stay in the tidyverse:

library(purrr)
library(dplyr)

map2(dfs, 3:4, ~ .x %>% mutate(z=.y))
[[1]]
  x z
1 1 3

[[2]]
  y z
1 2 4

You can also pipe the list into map2:

dfs %>% map2(3:4, ~ .x %>% mutate(z=.y))
eipi10
  • 91,525
  • 24
  • 209
  • 285