1

I'm looking for some help in defining a function to reverse code an ordinal variable. I'm using survey data in which theoretically related variables are coded in different directions i.e, perceptions of a concept are measured with several different variables, some of which denote higher values as "positive", others denote lower values as "positive". I've written a function that allows me to reverse code the selected variables so that they are consistently coded:

reverse_code <- function(x, df){
  df[x] <- df[x] * -1 + max(df[x], na.rm = TRUE) + 1
  return(df)
}

# call the function - note that var names need to be quoted, but not the dataframe
data <- reverse_code(c("var1", "var2", "var3", "var4"), data)

but it is sensitive to quotation marks as you see in my code comment above. The variable names need to be quoted, but not the dataframe. Any thoughts on how I could make this work so that it were insensitive to the inclusion/exclusion of quotation marks? I thought about including an if/else statement at the beginning to test for quotes, but I'm not sure how I would do this.

I realize that this function already assumes that the data have been cleaned of negative values, which for data that I typically use, almost exclusively denote missing values.


Edit:

As per a comment, to clarify, I would like for it to not matter if I called the function like this:

reverse_code(var1, data)

or like this:

reverse_code("var1", data)
zx8754
  • 52,746
  • 12
  • 114
  • 209
dj20b22
  • 73
  • 6
  • 1
    I do not understand the issue. It's standard in R that character strings are indicated by quotation marks whereas symbols are (of course) not. I don't understand how/why you want to pass a vector of symbols instead of characters. Please explain in more detail and show how you would want to call the function with non-standard evaluation. PS: In any case, it's a bad idea and you should reconsider. – Roland Jun 01 '18 at 07:45
  • Right, I was unclear. I would like to be able to call the function like this as well: reverse_code(var1, data) – dj20b22 Jun 01 '18 at 08:09
  • I appreciate if you think this is not the best approach, but this type of recoding is something that I have to do very often with the data that I use. If you have a better approach I would gladly listen. – dj20b22 Jun 01 '18 at 08:11
  • OK, so you want to use non-standard evaluation if and only if `x` is length one? – Roland Jun 01 '18 at 08:12
  • And you never want to pass something to `x` programmatically? – Roland Jun 01 '18 at 08:13
  • Exactly. I've edited the original text to clarify. – dj20b22 Jun 01 '18 at 08:14
  • I think "passing programatically" may be beyond my abilities/needs. I'm not really sure what you mean to be honest. – dj20b22 Jun 01 '18 at 08:15
  • @Roland I think they want something like in *dplyr*: `dplyr::select(cars, dist)` vs `dplyr::select_(cars, "dist")` – zx8754 Jun 01 '18 at 08:18
  • "passing programatically" means `a <- "var1"; reverse_code(a, data)`. – Roland Jun 01 '18 at 08:21

1 Answers1

1

You can do something like this, using match.call:

foo <- function(x, df) {

  thecall <- match.call()

  if (is.symbol(thecall[["x"]])) return(paste0("NSE: ", as.character(thecall[["x"]])))
    else
  return(paste0("SE: ", x))  
}

foo(x)
#[1] "NSE: x"
foo("x")
#[1] "SE: x"

Or if you don't need additional handling, simply:

foo <- function(x, df) {

  thecall <- match.call()

  x <- as.character(thecall[["x"]])

  x
}

I don't think you should, but you can.

Roland
  • 127,288
  • 10
  • 191
  • 288
  • Awesome, thanks. I used the second option and it works well. I'll keep your skepticism in mind and read more about NSE. Like @zx8754 said, this is similar to dplyr functions so it never occurred to me that this might be something to avoid. – dj20b22 Jun 01 '18 at 10:10