rscala软件包:如何在R中访问Scala缓存的引用数组的元素

时间:2018-07-25 15:41:20

标签: arrays r scala

我正在使用rscala来传递Scala和R。可以说我有一个Scala函数,该函数返回Array [Double]和Double的Array:

Array(projectedTrainToMatrix,predictedTrain,kernelParam,projection,thresholdsToArray)

其中kernelParamDouble类型,其他是Array[Double]。当我从R运行方法时:

myfit<-s$.cristinahg.ocapis.kdlor$kdlorfit(traindata,trainlabels,kerneltype,params)

我得到myfit作为

ScalaCachedReference... _: Array[Array[_]]
[Ljava.lang.Object;@b9dfc5a

但是我想访问myfit数组中的每个值。我试图通过myfit$'(1)'访问它们,但我得到了这个,而不是所需的Double数组:

function (..., .AS.REFERENCE = NA, .EVALUATE = TRUE, .PARENTHESES = FALSE) 
{
    args <- list(...)
    if (!is.null(names(args))) 
        stop("Arguments should not have names.")
    names <- paste0(rep("$", length(args)), seq_len(length(args)))
    header <- mkHeader(args, names)
    identifier <- ""
    body <- if (inherits(reference, "ScalaInterpreterReference")) 
        paste0(reference[["identifier"]], ".", method)
    else if (inherits(reference, "ScalaCachedReference")) {
        if (.EVALUATE) {
            identifier <- reference[["identifier"]]
            paste0("R.cached($0).asInstanceOf[", reference[["type"]], 
                "].", method)
        }
        else {
            paste0("R.cached(\\"", reference[["identifier"]], 
                "\\").asInstanceOf[", reference[["type"]], "].", 
                method)
        }
    }
    else if (inherits(reference, "ScalaInterpreterItem")) {
        if (method == "new") 
            paste0("new ", reference[["snippet"]])
        else paste0(reference[["snippet"]], ".", method)
    }
    else stop("Unrecognized reference type.")
    argsList <- paste0(names, collapse = ",")
    if ((nchar(argsList) > 0) || .PARENTHESES) 
        argsList <- paste0("(", argsList, ")")
    snippet <- paste0(header, paste0(body, argsList))
    if (get("show.snippet", envir = interpreter[["env"]])) 
        cat("<<<\\n", snippet, "\\n>>>\\n", sep = "")
    cc(interpreter)
    wb(interpreter, DEF)
    wc(interpreter, snippet)
    flush(interpreter[["socketIn"]])
    status <- rb(interpreter, "integer")
    if (status != OK) {
        if (get("serializeOutput", envir = interpreter[["env"]])) 
            echoResponseScala(interpreter)
        stop("Problem defining function.")
    }
    functionName <- rc(interpreter)
    if (get("serializeOutput", envir = interpreter[["env"]])) 
        echoResponseScala(interpreter)
    f <- function(..., .NBACK = 1) {
        args <- list(...)
        if (length(args) != length(names)) 
            stop("Incorrect number of arguments.")
        if (!is.null(names(args))) 
            stop("Arguments should not have names.")
        workspace <- new.env(parent = parent.frame(.NBACK))
        assign(".rsI", interpreter, envir = workspace)
        for (i in seq_len(length(args))) assign(names[i], args[[i]], 
            envir = workspace)
        cc(interpreter)
        wb(interpreter, INVOKE)
        wc(interpreter, functionName)
        wc(interpreter, identifier)
        flush(interpreter[["socketIn"]])
        rServe(interpreter, TRUE, workspace)
        status <- rb(interpreter, "integer")
        if (get("serializeOutput", envir = interpreter[["env"]])) 
            echoResponseScala(interpreter)
        if (status != OK) 
            stop("Problem invoking function.")
        result <- scalaGet(interpreter, "?", .AS.REFERENCE)
        if (is.null(result)) 
            invisible(result)
        else result
    }
    if (.EVALUATE) 
        f(..., .NBACK = 2)
    else f
}
<bytecode: 0x55b1ba98b3f8>
<environment: 0x55b1bd2616c0>

那么我如何在R中访问Scala数组的每个元素?

1 个答案:

答案 0 :(得分:3)

您的示例显示您正在使用rscala <3.0.0。尽管可以在旧版本中完成,但我建议您使用recent version on CRAN。下面,我提供使用rscala 3.1.0的解决方案。

library(rscala)
scala()

s + ' 
  def kdlorfit(
    projectedTrainToMatrix: Array[Double], predictedTrain: Array[Double],
    kernelParam: Double, projection: Array[Double], thresholdsToArray: Array[Double]) =
  {
    Array(projectedTrainToMatrix,predictedTrain,kernelParam,projection,thresholdsToArray)
  }
'

x1 <- c(1,2,3)
x2 <- c(11,12,13)
x3 <- 34
x4 <- c(100,110,120)
x5 <- c(50,51)

myfit <- s$kdlorfit(x1,x2,x3,x4,x5)
scalaType(myfit)

identical(x1,myfit(0L)$"asInstanceOf[Array[Double]]"())
identical(x3,myfit(2L)$"asInstanceOf[Double]"())

请注意,由于asInstanceOf的Scala类型为myfit,因此需要使用Array[Any]进行投射。

如果函数返回的是Array[Array[Double]]而不是Array[Any],则不需要强制转换,如下所示。

s + ' 
  def kdlorfit2( 
    projectedTrainToMatrix: Array[Double], 
    predictedTrain: Array[Double], 
    kernelParam: Array[Double], 
    projection: Array[Double], 
    thresholdsToArray: Array[Double]) = 
  { 
    Array(projectedTrainToMatrix,predictedTrain,kernelParam,projection,thresholdsToArray) 
  } 
' 

myfit <- s$kdlorfit2(x1,x2,I(x3),x4,x5) 
scalaType(myfit) 

identical(x1,myfit(0L)) 
identical(x3,myfit(2L)) 

请注意,在调用kdlorfit2时,参数x3Array[Double]的形式传递,因为它包装在I()中。如上例所示,它不进行包装就作为Double传递。