4

I'm trying to make my own function wrapping dplyr functions.

I have a list of dataframes and I would like to modify the levels of a specified variable with given labels (both should be function's parameters).

This is what I tried so far :

library(plyr); library(dplyr)

groups <- list(label1 = "setosa", label2 = c("virginica", "versicolor"))

iris$Species <- as.character(iris$Species)
x <- lapply(1:5, function(x) iris)

f <- function(datas, fillVar, groups) {

  fillStr <- deparse(substitute(fillVar))

  datas <- llply(datas, function(x) {
    x <- mutate_(x, .dots = setNames(list(lazyeval::interp(~ factor(var), var = substitute(fillStr))), fillStr))
    levels(x[,fillStr]) <- groups
    return(x)})

  return(datas)
}

f(x, Species, groups)

 Error in mutate_impl(.data, dots) : object 'Species' not found 

But I can't make it works and I just don't understand why... Do you know what I am missing ? Thanks.

Julien Navarre
  • 7,653
  • 3
  • 42
  • 69
  • `x <- lapply(1:5, function(x) iris)` is for reproduce my datas. I have a list of dataframes with common variables – Julien Navarre Jul 09 '15 at 08:47
  • @akrun `plyr::mutate_` doesn't exist, doesn't seem to be a namespace problem. And you are right I didn' notice but `f(x, 'Species', groups)` works, but I would like to keep the "dplyr function syntax" in my function and pass as argument the variable unquoted if possible – Julien Navarre Jul 09 '15 at 08:54

1 Answers1

3

Try

f1 <- function(datas, fillVar, groups) {
  fillStr <- deparse(substitute(fillVar))
  datas <- llply(datas, function(x) {
     x <- mutate_(x, .dots = setNames(list(lazyeval::interp(~ factor(var),
                var = as.name(fillStr))), fillStr))
    levels(x[fillStr]) <- groups
    x})
   return(datas)
}

 identical(f(x, 'Species', groups), f1(x, Species, groups))
 #[1] TRUE
akrun
  • 874,273
  • 37
  • 540
  • 662
  • 1
    Thanks !! `as.name` is exactly what I need. You solve my problem and now this step works you make me realize that my function doesn't exactly do what I wanted. I will edit when I fix it. – Julien Navarre Jul 09 '15 at 09:08
  • @JulienNavarre May be you need to return `x` i.e. `levels(x[fillStr]) <- groups; x})` in the function – akrun Jul 09 '15 at 09:14
  • You are absolutely right, and I have to use `levels(x[ ,fillStr])` instead of `levels(x[fillStr])` for levels assignement. – Julien Navarre Jul 09 '15 at 09:17
  • @JulienNavarre I just checked the `levels(x[,fillStr])`, It creates an NA column – akrun Jul 09 '15 at 09:21
  • with your `as.name` solution I have the expected output using `levels(x[,fillStr])` and the levels aren't changed using `levels(x[fillStr])` (I think you got NAs because you tested it with `substitute(fillStr)` no ?) – Julien Navarre Jul 09 '15 at 09:26