Search code examples
roopr-s4mlr

R OOP change the name of a slot


I'm using MLR package and I stumbled on a problem with an S4 object. More specifically it's the slot name that causes the trouble. I'm looking for a way to change the slot's name, not the value.

Here's a reproducible code example that generates the object in question:

lrn1 = makeLearner("classif.lda", predict.type = "prob")
lrn2 = makeLearner("classif.ksvm", predict.type = "prob")
lrns = list(lrn1, lrn2)
rdesc.outer = makeResampleDesc("CV", iters = 5)

ms = list(auc, mmce)

bmr = benchmark(lrns, tasks = sonar.task, resampling = rdesc.outer, 
                measures = ms, show.info = FALSE)


preds = getBMRPredictions(bmr, drop = TRUE)


ROCRpreds = lapply(preds, asROCRPrediction)


ROCRperfs = lapply(ROCRpreds, function(x) ROCR::performance(x, "tpr", "fpr"))

The object is made of two lists and I need to change the name slots in both of them. Instead of x.values and y.values the names should be x and y respectively.

str(ROCRperfs$classif.lda)

Formal class 'performance' [package "ROCR"] with 6 slots
  ..@ x.name      : chr "False positive rate"
  ..@ y.name      : chr "True positive rate"
  ..@ alpha.name  : chr "Cutoff"
  ..@ x.values    :List of 5
  .. ..$ : num [1:43] 0 0 0 0 0 ...
  .. ..$ : num [1:42] 0 0 0 0.0526 0.0526 ...
  .. ..$ : num [1:42] 0 0 0 0.05 0.05 0.05 0.05 0.05 0.05 0.05 ...
  .. ..$ : num [1:43] 0 0 0.0476 0.0476 0.0476 ...
  .. ..$ : num [1:43] 0 0 0 0 0 ...
  ..@ y.values    :List of 5
  .. ..$ : num [1:43] 0 0.0417 0.0833 0.125 0.1667 ...
  .. ..$ : num [1:42] 0 0.0455 0.0909 0.0909 0.1364 ...
  .. ..$ : num [1:42] 0 0.0476 0.0952 0.0952 0.1429 ...
  .. ..$ : num [1:43] 0 0.0476 0.0476 0.0952 0.1429 ...
  .. ..$ : num [1:43] 0 0.0435 0.087 0.1304 0.1739 ...
  ..@ alpha.values:List of 5
  .. ..$ : num [1:43] Inf 1 1 1 1 ...
  .. ..$ : num [1:42] Inf 1 1 1 0.999 ...
  .. ..$ : num [1:42] Inf 1 1 1 1 ...
  .. ..$ : num [1:43] Inf 1 1 0.999 0.999 ...
  .. ..$ : num [1:43] Inf 1 1 1 1 ...

As I'm beginner to OOP in R all I could was to print the slot with slot().

The bottom line is that all I want to do with the object in question is to plot is as follows:

plot(ROCRperfs[[1]], col = "blue", avg = "vertical", spread.estimate = "stderror",
  show.spread.at = seq(0.1, 0.8, 0.1), plotCI.col = "blue", plotCI.lwd = 2, lwd = 2)

Solution

  • You cannot change the structure of an S4 class once it's defined. This is a feature, not a bug. By imposing restrictions on what can be done, S4 reduces the chance of bugs creeping into your code.

    For example, consider what might happen if you changed the slotnames in the object to x and y, and then passed the object to a function that's expecting x.values and y.values. By not allowing you to make this change, S4 rules out the possibility that code down the line will be given an object whose structure they can't handle.

    For your use case, you can just plot the x.values and y.values slots individually:

    plot(ROCRperfs[[1]]@x.values, ROCRperfs[[1]]@y.values,
         col = "blue", avg = "vertical", spread.estimate = "stderror",
         show.spread.at = seq(0.1, 0.8, 0.1), plotCI.col = "blue",
         plotCI.lwd = 2, lwd = 2))