John Smith
John Smith

Reputation: 2876

R - Passing a column name to a function to be evaluated in a non standard way

I have a data-frame where I want to pass a column name to R in and then filter based on that column. I have tried reading a few tutorials on this and it seems to be related to non standard evaluation in R.

I cant seem to wrap my head around the examples in the blog posts I have read. Just for simplicity, I have taken the iris dataset and I want to pass a column to a function which will then filter that dataset where the column value is greater than one.

mydf <- iris

filter_measurements <- function(mydf, measurement){

  mydf <- filter(measurement >= 1)
  mydf

}

mydf %>% 
  filter_measurements(measurement = Petal.Width)

Do I have to add something to my function so that R knows I want a column and not use it as 'Petal.Width' for example.

I have seen Passing a variable name to a function in R which i was unable to adapt to my example

Thank you all for your time

Upvotes: 0

Views: 389

Answers (2)

lontche
lontche

Reputation: 46

You have to pass the column name either as character or integer index of the column. Also, the line

mydf <- filter(measurement >= 1)

within your function never states what is being filtered and will expect the "measurement" to be a stand-alone object, not a part of a data frame. Try this:

filter_measurements <- function(mydf, measurement)
{
  mydf <- filter(mydf, mydf[,measurement] >= 1)
  mydf
}

iris %>% filter_measurements("Petal.Width")

A more convoluted invocation of the function would also work:

iris %>% filter_measurements(which(names(.)=="Petal.Width"))

Upvotes: 1

kath
kath

Reputation: 7724

A great resource for this is Programming with dplyr.

mydf <- iris

filter_measurements <- function(mydf, measurement){
  measurement <- enquo(measurement)

  mydf <- filter(mydf, (!!measurement) >= 1)
  mydf

}

mydf %>% 
  filter_measurements(measurement = Petal.Width)

You have to tell the function that measurement is giving as a bare variable name. For this first use enquo to evaluate what is given in the measurement argument and store it as a quosure. Then with !! in front of measurement the filter function knows that it doesn't have to quote this argument, as it is already a quosure.

Alternative

You can also pass the column you want to filter on as a string and use filter_:

filter_measurements <- function(mydf, measurement){

  mydf <- filter_(mydf, paste0(measurement, " >= 1"))
  mydf

}

mydf %>% 
  filter_measurements(measurement = "Petal.Width")

Upvotes: 2

Related Questions