1

Consider this simple example

library(dplyr)
library(purrr)

mydata <- dplyr::data_frame('value' = c(1,2,3))
> mydata
# A tibble: 3 x 1
  value
  <dbl>
1    1.
2    2.
3    3.

I have a function that takes the dataframe and a number as arguments, and I would like to modify the dataframe in place at each iteration.

I have written the following, but it does not update the dataframe:

  myfunc <- function(df, numba){
  name_var <- paste('year_', quo_name(numba), sep ='')
  df <- df %>% mutate(!!name_var := 1)
  return(df)
}

seq(2006, 2007, by = 1) %>% 
    purrr::walk(function(x) {mydata <- myfunc(mydata, x)})

Unfortunately mydata is not modified correctly:

seq(2006, 2007, by = 1) %>% 
    map(function(x) {mydata <- myfunc(mydata, x)})

gives:

[[1]]
# A tibble: 3 x 2
  value year_2006
  <dbl>     <dbl>
1    1.        1.
2    2.        1.
3    3.        1.

[[2]]
# A tibble: 3 x 2
  value year_2007
  <dbl>     <dbl>
1    1.        1.
2    2.        1.
3    3.        1.

while the expected output should be

# A tibble: 3 x 3
  value year_2006 year_2007
  <dbl>     <dbl>     <dbl>
1    1.        1.        1.
2    2.        1.        1.
3    3.        1.        1.

What am I missing here? Thanks!

ℕʘʘḆḽḘ
  • 18,566
  • 34
  • 128
  • 235

2 Answers2

1

map returns results as a list. You can use map_dfc to bind results for each year by column then remove the extra value columns

    seq(2006, 2007, by = 1) %>% 
      map_dfc(function(x) {mydata <- myfunc(mydata, x)}) %>% 
      select(value, matches("year_"))

    # or even shorter
    seq(2006, 2007, by = 1) %>% 
      map_dfc(~ myfunc(mydata, .)) %>% 
      select(value, matches("year_"))

    # A tibble: 3 x 3
      value year_2006 year_2007
      <dbl>     <dbl>     <dbl>
    1    1.        1.        1.
    2    2.        1.        1.
    3    3.        1.        1.
Tung
  • 26,371
  • 7
  • 91
  • 115
-3

First, be should mydata <- data.frame('value' = c(1,2,3)), not mydata <- data_frame('value' = c(1,2,3)). Now, to solve your problem you should return the dataframe to modify it. Like this:

myfunc <- function(df, numba){
    name_var <- paste('year_', quo_name(numba), sep ='')
    df <- df %>% mutate(name_var = 1)
    return(df)
}

EDIT

Try using

seq(2006, 2007, by = 1) %>% 
 map(function(x) {mydata <- myfunc(mydata, x)})
Kim Ruan
  • 90
  • 1
  • 10
  • the dataframe is still not updated after the `purrr` call unfortunately – ℕʘʘḆḽḘ Mar 07 '18 at 15:17
  • Using map it worked here, but not the same way in your example. Take a look in your function. – Kim Ruan Mar 07 '18 at 15:33
  • please see updated question. I have changed my function so that it works better. – ℕʘʘḆḽḘ Mar 07 '18 at 15:45
  • The command `seq(2006, 2007, by = 1) %>% map(function(x) {mydata <- myfunc(mydata, x)})` return a data of type list. So, its not the better way to fix your problem, but you can try tranform the type to `dataframe`. Like this: `new_table <- seq(2006, 2007, by = 1) %>% map(function(x) {mydata <- myfunc(mydata, x)})`. And then: `new_table <- as.data.frame(new_table)`. – Kim Ruan Mar 07 '18 at 17:27