1
$\begingroup$

In our usage of R for a non-trivial data analysis and estimation project, we've been repeatedly burnt by how tolerant R is toward misspelled or missing columns in a data frame. Typical example is calculating the weighted mean of a variable MYVAR in a data frame using another variable WEIGHT for weights:

m <- weighted.mean(tbl$MYVAR, w = tbl$WEIGHT, na.rm = TRUE)

Suppose I make a typo in the WEIGHT name in the operation above. What will happen in that R will expand my misspelled column into NULL and will use it for performing the weighted mean resulting in a non-weighted one.

Therefore, the question: is there any way to make R treat attempts to "read" a non-existent variables in a data frame as an error?

$\endgroup$
3
$\begingroup$

Hmm... when I tried out your example with some fake data, weighted.mean() actually failed:

#Some fake data
dat <- data.frame(x = rnorm(100), weight = rnorm(100))

#The right weight var
weighted.mean(x = dat$x, w = dat$weight)
[1] 0.6161606

#Misspelled weight var
weighted.mean(x = dat$x, w = dat$wieght)
Error in weighted.mean.default(x = dat$x, w = dat$wieght) : 
  'x' and 'w' must have the same length

But anyway, another way to cope with this problem is to access your variables via indexing - it returns an error if you try to pick non-existant columns:

dat$wieght
NULL

dat[ , "wieght"]
Error in `[.data.frame`(dat, , "wieght") : undefined columns selected

weighted.mean(x = dat[ , "x"], w = dat[ , "wieght"], na.rm = TRUE)
Error in `[.data.frame`(dat, , "wieght") : undefined columns selected
$\endgroup$
3
  • $\begingroup$ Yes, this would definitely work but you have to admit that the syntax is somewhat unwieldy. dat[ , "WEIGHT"] is a lot less elegant compared to dat$WEIGHT. I just wondered why there is no option to turn on the behavior above? This sounds like a very reasonable feature. $\endgroup$ – Alexander L. Belikoff Nov 10 '10 at 22:14
  • $\begingroup$ Also, on the heels of my last comment. I wonder if using attaching the data frame and then referencing the variables directly would mitigate this problem... $\endgroup$ – Alexander L. Belikoff Nov 10 '10 at 22:17
  • 2
    $\begingroup$ I would definitely avoid using attach in all circumstances, but I think that's the right idea. You can use with() to attach a data frame for a single command: with(dat, weighted.mean(x, weight, na.rm = TRUE)). Also, many functions like weighted.mean include a data= option that essentially internalizes this. $\endgroup$ – Matt Parker Nov 10 '10 at 22:39
1
$\begingroup$

Maybe, you can enclose your code into try-catch blocks, see ?try and the associated examples. It is easy to test for the class of the results ("try-error") in turn, e.g.

> res <- try(log("A"), silent=TRUE)
> class(res)
[1] "try-error"

You can also test directly for the correct spelling, by first listing the variables of interest--in your case, MYVAR and WEIGHT-- and test that they are part of the data.frame df, e.g.

df <- data.frame(x=rnorm(100), g1=gl(2, 50), g2=gl(5,20))
sel.vars <- c("x","g2")
ifelse(all(sel.vars %in% colnames(df)), <compute things here>, "fail") 
$\endgroup$
1
  • $\begingroup$ Unfortunately, the snippet above would not help. Making sure that all columns (variables) are present in the data frame is one thing and it would never help against accidental misspelling of a variable name in some other corner of the code. $\endgroup$ – Alexander L. Belikoff Nov 10 '10 at 22:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.