0

Sorry for the basic question, but I could not find an example in this forum to solve this question. I've tried this one and this one.

I want to change / create a new variable in my data.frame via function in R and tidyverse:

Example:

crivo <- function(x) {
  x <<- x %>% 
    mutate(resp_1 = if_else(MEMO_RE01 == 0,"VN","FP")) %>% 
    mutate(resp_2 = if_else(MEMO_RE02 == 1,"VP","FN"))
  }
crivo(memo_re)

My data.frame name is "memo_re", but I'll use this function to other datasets as well, just by changing the x argument. R is creating a new data.frame named x instead of creating a new variable in "memor_re" (original dataset). In other words, I want to assign a function to do that:

memo_re <- memo_re %>% mutate(resp_1 = if_else(MEMO_RE01 == 0,"VN","FP"))

But I need to change many datasets and because of that, I want to be able to specify which dataset I'll change.

reproducible code

library(tidyverse)
memo_re <- data.frame(MEMO_RE01=rep(c(0,1),100), MEMO_RE02=c(0,1))

crivo <- function(x) {
  x <<- x %>% 
    mutate(resp_1 = if_else(MEMO_RE01 == 0,"VN","FP")) %>% 
    mutate(resp_2 = if_else(MEMO_RE02 == 1,"VP","FN"))
}
crivo(memo_re)
Steven
  • 3,238
  • 21
  • 50
Luis
  • 1,388
  • 10
  • 30
  • I'm not sure if I understand the question. The code as you've provided it works just fine for me, though I think it's strange that you're just assigning `x` to the environment rather than returning it from the `crivo()` function. – Steven Feb 01 '18 at 17:24
  • Can you give data example? – Onyambu Feb 01 '18 at 17:25
  • Sure. You can simulate data.frame using this code: library(tidyverse) memo_re <- data.frame(MEMO_RE01=rep(c(0,1),100), MEMO_RE02=c(0,1)) crivo <- function(x) { x <<- x %>% mutate(resp_1 = if_else(MEMO_RE01 == 0,"VN","FP")) %>% mutate(resp_2 = if_else(MEMO_RE02 == 1,"VP","FN")) } crivo(memo_re) – Luis Feb 01 '18 at 17:26
  • I edited my original post to clarify my question. Thanks. – Luis Feb 01 '18 at 17:31
  • you will have to use quosure format since in tidyverse function arguments are evaluated lazily using promise – Onyambu Feb 01 '18 at 17:36
  • Thanks, but could you please provide some link or reference? First time I heard about "quosure format". Thanks! @Onyambu – Luis Feb 01 '18 at 17:40
  • sorry you did ask for a link. Am so sorry. you can check [here](http://dplyr.tidyverse.org/articles/programming.html) – Onyambu Feb 01 '18 at 18:06

1 Answers1

2

R is doing exactly what you've asked it to do. In your crivo function definition, you've written your function to assign the new data frame you've created called x to the R environment. That's what the <<- operator does. After running your code, use ls() to see what's in your environment, then look at x. You'll see everything is there, just as you've asked it to be, including the correctly mutate x dataframe.

> memo_re <- data.frame(MEMO_RE01=rep(c(0,1),100), MEMO_RE02=c(0,1))
> 
> crivo <- function(x) {
+   x <<- x %>% 
+     mutate(resp_1 = if_else(MEMO_RE01 == 0,"VN","FP")) %>% 
+     mutate(resp_2 = if_else(MEMO_RE02 == 1,"VP","FN"))
+ }
> crivo(memo_re)
> ls()
[1] "crivo"   "memo_re" "x"      
> head(x)
  MEMO_RE01 MEMO_RE02 resp_1 resp_2
1         0         0     VN     FN
2         1         1     FP     VP
3         0         0     VN     FN
4         1         1     FP     VP
5         0         0     VN     FN
6         1         1     FP     VP

Now, if you wanted to have crivo() return something that you could then assign any name you wanted, you should use

crivo <- function(x) {
  x %>% 
    mutate(resp_1 = if_else(MEMO_RE01 == 0,"VN","FP"), 
           resp_2 = if_else(MEMO_RE02 == 1,"VP","FN"))
}

Note that I haven't used the <<- operator anywhere. As a result, the crivo fx will be returning the mutated x dataframe so that you could do

new <- memo_re %>% crivo()

This way, you can pipe anything you want to crivo and assign it to any new variable. Alternatively, if you just wanted to call the function on memo_re, you can do that too:

memo_re <- memo_re %>% crivo()

Note that the "classic" way to write a function is to use return() to specify what you want a fx to return. If you don't use return() (as I haven't above), R will return whatever is in the last line. Here, it's just the mutate dataframe.

Steven
  • 3,238
  • 21
  • 50
  • Thanks much, @Steven, I want to know If it is possible to _instead of using memo_re <- memo_re %>% crivo()_ use something like _crivo(dataset I want to mutate)_ ? – Luis Feb 01 '18 at 17:59
  • Of course it is. Using `memo_re %>% crivo()` is the same as writing `crivo(memo_re)`. Either way, if you want to reuse whatever comes from `crivo()`, you'll need to assign the output to some variable. – Steven Feb 01 '18 at 18:05
  • Thanks, because English is not my first language, I think I'm not being precise. Is it possible to crivo(memo_re) get _"memo_re" dataset_, create a _new variable_ and update _this dataset_? I want to use _this same crivo function_ in _several datasets_. Example crivo(memo_re) will do that in "memo_re" dataset, but crivo(memo_2) will do this function in "memo_2). Thanks again, @Steven – Luis Feb 01 '18 at 18:09
  • 1
    So, `memo_re <- crivo(memo_re)` is unacceptable? As would be `memo_2 <- crivo(memo_2)`, etc.? You want `crivo(some_dataframe)` to mutate the `some_dataframe` dataframe and also update the *existing* `some_dataframe` in the current `R` environment? I think the latter is very bad software design and could have unintended consequences. – Steven Feb 01 '18 at 18:16
  • Your answer is totally acceptable! Thanks much! I just ask that for curiosity and to discover if this function will be possible to do in R! Thanks much again, @Steven !! – Luis Feb 01 '18 at 18:37