0

I have this function to take an object returned by the IRT package sirt and plot item response functions for a set of items that the user can specify:

plotRaschIRF <- function(x,items=NULL,thl=-5,thu=5,thi=.01,D=1.7) {
  if (!class(x)=="rasch.mml") stop("Object must be of class rasch.mml")
  thetas <- seq(thl,thu,thi)
  N <- length(thetas)
  n <- length(x$item$b)
  tmp <- data.frame(item=rep(1:n,each=N),theta=rep(thetas,times=n),b=rep(x$item$b,each=N))
  probs <- exp(D*(tmp[,2]-tmp[,3]))/(1+exp(D*(tmp[,2]-tmp[,3])))
  dat <- data.frame(item=rep(1:n,each=N),theta=rep(thetas,times=n),b=rep(x$item$b,each=N),p=probs)
  #dat$item <- factor(dat$item,levels=1:n,labels=paste0("Item",1:n))
  if (is.null(items)) {
    m <- min(10,n)
    items <- 1:m
    if (10<n) warning("By default, this function will plot only the first 10 items")
  }
  if (length(items)==1) {
    title="Item Response Function"
  } else {
    title="Item Response Functions"
  }
  dat2 <- subset(dat,eval(quote(eval(item,dat) %in% items)))
  dat2$item <- factor(dat2$item,levels=unique(dat2$item),labels=paste0("Item",unique(dat2$item)))
  out <- ggplot(dat2,aes(x=theta,y=p,group=item)) +
   geom_line(aes(color=dat2$item),lwd=1) + guides(col=guide_legend(title="Items")) +
   theme_bw() + ggtitle(title) + xlab(expression(theta)) +
   ylab("Probability") + scale_x_continuous(breaks=seq(thl,thu,1))
  print(out)
}

But it seems to be getting stuck at either the line just before I start using ggplot2 (where I convert one column of dat2 to a factor) or at the ggplotting itself -- not really sure which. I get the error message "Error in eval(expr, envir, enclos) : object 'dat2' not found".

I tried reading through this as was suggested here but either this is a different problem or I'm just not getting it. The function works fine when I step through it line by line. Any help is greatly appreciated!

Community
  • 1
  • 1
Jon
  • 753
  • 8
  • 18
  • Is this line: `subset(dat,eval(quote(eval(item,dat) %in% items)))` really just trying to select the rows of `dat` where the values of the column `item` are in the vector `items`? – joran Feb 10 '14 at 20:07
  • Save yourself the heartache and don't use `subset` inside a function. It's meant for interactive use. Why don't you `dat2 <- dat[dat$item %in% items, ]` – BrodieG Feb 10 '14 at 20:08
  • yes that's all it's meant to do, and I actually originally had what @BrodieG suggests, but I originally thought the error message was due to this line and went on a whole eval spree to try to fix it before realizing it wasn't that (or, at least, subsequent lines still led to the same error message). I don't think the problem is here -- the function will get past this line before crashing (I can have it print stuff in between that terrible line and the next line). – Jon Feb 10 '14 at 20:24
  • It might be better to use the `fortify` approach that`ggplot2` implements for `lm` objects. Once you have written a fortify.raschmml method that creates data frame, which you can then call `ggplot` more easily – mnel Feb 11 '14 at 01:45
  • I hadn't heard of `fortify`, thanks for the heads-up – Jon Feb 12 '14 at 02:45

1 Answers1

2

Based on your comments, the error is almost certainly in geom_line(aes(color=dat2$item)). Get rid of dat2$ and it should work fine (i.e. geom_line(aes(color=item))). Stuff in aes is evaluated in the data argument (dat2 here), with the global environment as the enclosure. Notably this means stuff in the function environment is not available for use by aes unless it is part of the data (dat2 here). Since dat2 doesn't exist inside dat2, and dat2 doesn't exist in the global environment, you get that error.

BrodieG
  • 51,669
  • 9
  • 93
  • 146
  • 1
    ...and for goodness sakes get rid of that `subset(eval(quote(eval()))` nonsense! :) – joran Feb 10 '14 at 20:43
  • Yes!! Thank you so much, I didn't even suspect the geom_line bit (when stepping through the function it didn't work unless I had dat2$item there). And yes @joran that terrible line is gone (I didn't want it there to begin with!) – Jon Feb 10 '14 at 20:44