Tao Hu Tao Hu - 3 months ago 22
R Question

something about Use character string as function argument in R

I want to create new columns by using the original columns subtract each other, I use character to express all the combination of new columns, then I want to use

dplyr::mutate
to create new columns. There are something wrong in
foo <- eval(parse(text = paste(new.feature,collapse = ",")))
, thank you for your answer.

col.names <- names(iris)
sign.paste <- function(x){paste(x,collapse = "-")}
new.feature <- apply(combn(col.names,2),2,sign.paste)
paste(new.feature,collapse = ",")
foo <- eval(parse(text = paste(new.feature,collapse = ",")))
dplyr::mutate(iris,foo)


when I use
paste(new.feature,collapse = ",")
, I will get a character like these

paste(new.feature,collapse = ",")



[1] "Sepal.Length-Sepal.Width,Sepal.Length-Petal.Length,Sepal.Length-Petal.Width,Sepal.Length-Species,Sepal.Width-Petal.Length,Sepal.Width-Petal.Width,Sepal.Width-Species,Petal.Length-Petal.Width,Petal.Length-Species,Petal.Width-Species"


Finally, I want to use
mutate
to create new columns, but failed..

Answer

You can't just mix and match strings and proper language expressions. It's also better to avoid eval() if possible. Here's a way to build an expression to define all the subtractions and then carry it out.

col.names <- names(iris)[sapply(iris, is.numeric)]
sign.paste <- function(x){substitute(x-y, list(x=as.name(x[1]), y=as.name(x[2])))}
new.feature <- apply(combn(col.names,2),2,sign.paste)

dplyr::mutate_(iris,.dots=new.feature)

Note that now sign.paste returns a list of language expressions, not strings. This is basically what you'd set if you eval-ed the strings. And then we make sure to use mutate_ which is the standard evaluation version of the mutate function. It allows us to pass parameters as a big list rather than separate parameters. See vignette("nse") for more info. (I also limited to just the numeric columns to avoid warnings about subtraction of factors)