2

This feels like a very beginner question.

In R, is there any way to use the $ operator based on parameters passed to a function?

I'm trying to write a simple function:

subs <- function(x, y){
  x<- subset(x, x$UR!=0)
  x<- subset(x, !is.na(x$y))
  x
}

This returns:

Warning message:
In is.na(x$y) : is.na() applied to non-(list or vector) of type 'NULL'

Because I have over 30 columns, counting it out to do this with [y] would not be useful.

Is there any way to dynamically call using $ within a function?

Thank you.

David Gerrard
  • 161
  • 1
  • 9
  • 2
    It is better to use `[` inside a function than `subset` i.e. `x <- x[x[, 'UR]!=0,]` Also, you don't need `x$` inside `subset` – akrun Aug 10 '15 at 13:55
  • In general, try to not use `subset` in your programs. [It can have surprising output!](http://stackoverflow.com/questions/9860090/in-r-why-is-better-than-subset) – rbatt Aug 10 '15 at 14:26

3 Answers3

4

Expanding on @akrun's comment:

subs <- function(x, y){
  x <- x[x[,"UR"]!=0,]
  x <- x[!is.na(x[,y]),]
  x
}

Where your call to the function would look like subs(dataframe, "variable.name"), with the latter in quotes.

The expression inside the brackets in each of the first two lines returns a vector of TRUE/FALSE values identifying the rows in x that satisfy the specified condition (e.g., for row i in x, the value of column "UR" is not equal to 0). Putting that in brackets adjacent to x with a comma after the expression uses that vector to select from x only those rows (hence the trailing comma) for which the result of the nested expression is TRUE.

N.B. This answer assumes that UR is the name of a variable in that dataframe.

ulfelder
  • 5,305
  • 1
  • 22
  • 40
1

In general, when there's a special operator like * or + or %% or $ or [ (etc), the first step in using or accessing more information about that operator is to put it in quotes. You want the help page for $? Then do ?"$". Now, if you want to use that function in a non-standard fashion (as you want to do, and this is just fine), then you can make use to of do.call, and the first argument to that function is a function in quotes: do.call(what="$", ...) The next arguments to do.call involve a list of arguments to be passed to the what. This is much broad than what you asked, but I hope it is useful to you in the future.

Second, you don't need to use $. You can just specify a column name for your data.frame. Instead of data$col, try data[,"col"]. For a data.frame, those are the same. If data was a list, you could do data[["col"]].

Here are examples that specifically address your question:

# Data set to work with for examples
df <- data.frame(ran=rnorm(10), num=1:10)

# Function giving example of what you wanted
get.col <- function(dat, col){
    do.call("$", list(dat, col))
}
get.col(df, "ran")

# A function providing an alternative approach
get.col2 <- function(dat, col){
    dat[,col]
}
get.col2(df, "ran")
rbatt
  • 4,677
  • 4
  • 23
  • 41
0

You can use column names as follows:

Fist I load example data,

data(mtcars) head(mtcars

                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1

Re-write the function:

subs <- function(x){
  x<- subset(x, x[,"mpg"]!=21.0)
  x<- subset(x,!is.na(x[,"mpg"]))
  x
}


subs(mtcars)
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
bjoseph
  • 2,116
  • 17
  • 24