Niels Verburg - 25 days ago 6
R Question

Create ROC curve with for loop or sapply

After a lot of searching I could not find an answer to my problem. I would like to generate a ROC curve with the pROC pakkage using a for loop or sapply.

My database looks like this (only with 26 colums and 74 rows):

``````PT Bpt PA mnT1G mnT01
1   1  1   2.3   4.5
1   2  0   1.2   3.2
2   1  1   5.4   2.1
``````

I can make a ROC curve 'manually':

``````plot.new()
roc1 <- roc(cor.datT\$PA, cor.datT\$mT1G, percent=TRUE, partial.auc=c(100, 90), partial.auc.correct=TRUE,
partial.auc.focus="sens", ci=TRUE, boot.n=100, ci.alpha=0.9, stratified=FALSE, plot=TRUE, col= 'red')
roc2 <- roc(cor.datT\$PA, cor.datT\$mT01, plot=TRUE, add=TRUE, percent=roc1\$percent, col = 'blue')
``````

For 'automatic' I tried:

First roc curve always mnT1G:

``````rocT1G <- roc(cor.datT\$PA, cor.datT\$mnT1G, percent=TRUE, partial.auc=c(100, 90), partial.auc.correct=TRUE, partial.auc.focus="sens", ci=TRUE, boot.n=100, ci.alpha=0.9, stratified=FALSE, plot=TRUE, col= 'red')
``````

Add other roc curves (data\$Img are all the image names (like T1G, T01, etc) from another dataframe). I understand they all will be blue :

``````sapply(unique(data\$Img[data\$Img != "T1G"]), FUN = function(i) paste("roc",i,sep="") <- roc(cor.datT\$PA, cor.datT[paste("mn",i, sep = "")], plot=TRUE, add=TRUE, percent=rocT1G\$percent, col = 'blue'), simplify = FALSE)
``````

But I get this error:

Error in roc.default(cor.datT\$PA, cor.datT[paste("mn", i, sep = "")],
: Predictor must be numeric or ordered.

Same happens with for loop:

``````for (i in unique(data\$Img[data\$Img != "T1G"])){
plot.new()
rocT1G <- roc(cor.datT\$PA, cor.datT\$mnT1G, percent=TRUE, partial.auc=c(100, 90), partial.auc.correct=TRUE, partial.auc.focus="sens", ci=TRUE, boot.n=100, ci.alpha=0.9, stratified=FALSE, plot=TRUE, col= 'red')
paste("roc",i,sep="") <- roc(cor.datT\$PA, cor.datT[paste("mn",i, sep = "")], plot=TRUE, add=TRUE, percent=rocT1G\$percent, col = 'blue')
}
``````

I checked the columns and they are all numerical. So maybe something goes wrong with the class in my script?

As you noted in a comment on my other answer, the problem is that you get specifically `data.frame`s out of your extraction.

In a `data.frame`, extracting with a single character returns a `data.frame`. This is documented in ?Extract.data.frame:

Data frames can be indexed in several modes. When [ and [[ are used with a single vector index (x[i] or x[[i]]), they index the data frame as if it were a list.

And looking at ?Extract:

Recursive (list-like) objects

Indexing by [ is similar to atomic vectors and selects a list of the specified element(s).

This is not so obvious from the text, but in order to extract a column into a vector, you need to use two brackets `[[`, so

``````class(cor.datT[[paste("mn",i, sep = "")]])
``````

should be a vector.

Source (Stackoverflow)