0

I have a R code that looks something like this:

StatFunction <- function(CSVImport, AnimalID_i,Treatment_i){

  #Data Input from a CSV file (example below)
  Data <- read.csv(CSVImport)

All goes well so far, as the data is read off the csv file. I am calling the function like this

StatFunction (path/to/file/, "Animal", "Treatment")

Note that the input arguments are strings representing the column name of the CSV. Now, I try to sort out the data frame like this:

  #Trying to sort out the input
  Data <- within(Data, {

    FinalID <-  (factor(as.character(FinalID_i))) 
    AnimalID <- (factor(as.character(AnimalID_i))) 

This doesn't work with the argument of the StatFunction. It gives me this

[1] "---Final ID---"
[1] Treatment
Levels: Treatment
[1] "---Animal ID---"
[1] Animal
Levels: Animal

When, Substituting the arguments directly into the code, like this

    FinalID <-  (factor(Treatment))                
    AnimalID <- (factor(Animal))                   

It gives me the expected result.

    [1] "---Final ID---"
    [1] 0 0 1 1 1
    Levels: 0 1
    [1] "---Animal ID---"
    [1] 722 723 724 727 728
    Levels: 722 723 724 727 728

So my question is how to make this work when passing arguments and not burning the names in the code?

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
Rover Eye
  • 201
  • 1
  • 11
  • `with` and `within` are intended for interactive use, not programmatic inside functions. – Gregor Thomas Feb 03 '15 at 17:45
  • Also, break this into a minimal example. It doesn't matter that your input arguments are coming from a Shiny app, get the function working with `StatFunction("filename", "appropiate_animal_id", "some_final_id")`, and give us an example of what those arguments might actually be. – Gregor Thomas Feb 03 '15 at 18:04
  • thanks. Simplified the post. Does it make more sense now ? – Rover Eye Feb 03 '15 at 18:29
  • @Gregor, could you point me to a reference or indicate why `with` and `within` are intended for interactive use and not programmatic? There is no warning similar to the one in `?subset` or other indication on the help file so I thought there wouldn't be a problem. – talat Feb 03 '15 at 21:08
  • @docendodiscimus I *may* be overstating it above, but I think it's fair to say anything with nonstandard evaluation should be used with caution in a programmatic setting. With/within do come up [in this answer](http://stackoverflow.com/a/23324090/903061). A function using `with` will probably be fine most of the time, but a package with functions using `with` internally would not pass `R CMD CHECK`---it would at least warn about "no visual binding for global variables". – Gregor Thomas Feb 03 '15 at 21:44
  • Also from Hadley's [Non-Standard Evaluation](http://adv-r.had.co.nz/Computing-on-the-language.html) page, "This is an example of the general tension between functions that are designed for interactive use and functions that are safe to program with. A function that uses substitute() might reduce typing, but it can be difficult to call from another function." His specific example is `subset`, but the generalization is "anything that uses `substitute`". And if you look at the code for `with.default`, all it really is is `eval(substitute())`, a simpler version of `subset.data.frame`. – Gregor Thomas Feb 03 '15 at 21:50
  • It might be worth adding `subset`'s warning to the `with` documentation. – Gregor Thomas Feb 03 '15 at 21:51

2 Answers2

1

You can't just swap character and symbol values. If you want to extract data with a character value, then use

Data$FinalID <- factor(as.character(Data[[FinalID_i]]))
Data$AnimalID  <- factor(as.character(Data[[AnimalID_i]]))
MrFlick
  • 195,160
  • 17
  • 277
  • 295
0

Why not go back a step and add the fact that you want factor columns via their names by adding a colClasses argument that is passed to read.csv(). Or you can just add , ...) and do the same thing. The ... can be sent to the read.csv() argument list.

statFunction <- function(file, colClasses = character(), ...) {
    read.csv(file, colClasses = colClasses, ...)
}

And call statFunction() like this

statFunction(
    file, 
    colClasses = c(Animal = "factor", Treatment = "factor")
)
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245