Сумма многомерного массива Scala - PullRequest
2 голосов
/ 15 мая 2019

Я рассчитываю доверительный интервал для некоторых соотношений с использованием начальной загрузки для нескольких переменных, и каждая переменная имеет разные доверительные интервалы.

case class Limits(lowerLimit: Double, upperLimit: Double, confidenceInterval: Double)

case class CI(c85: Limits, c90: Limits, c95: Limits, c99: Limits)

Для начальной загрузки я запускаю цикл 100 раз.

val arrCIRatio: Array[CI] = Array()
var ci85: Limits = new Limits(0.0, 0.0, 0.0)
var ci90: Limits = new Limits(0.0, 0.0, 0.0)
var ci95: Limits = new Limits(0.0, 0.0, 0.0)
var ci99: Limits = new Limits(0.0, 0.0, 0.0)

val a = Array(1,2,3,4,5,6,7,8,9,10)
val rg = new scala.util.Random(100)

 for(iteration <- 1 to 100){
    val i= rg.nextInt(10)      
    ci85 = getInterval(a(i), 0.85)
    ci90 = getInterval(a(i), 0.90)
    ci95 = getInterval(a(i), 0.95)
    ci99 = getInterval(a(i), 0.99)

    arrCIRatio(iteration) = new CI(ci85,ci90,ci95,ci99)
}

После завершения цикла я хотел бы взять среднее значение каждого верхнего и нижнего пределов в CIмассив для всех ci85, ci89, ci95, ci99.

Я могу использовать foldLeft для вычисления суммы

x.foldLeft(0.0)( (x, y) => x + y.lowerLimit, x.foldLeft(0.0)( (x, y) => x + y.upperLimit

или наивным способом:

var avgci85: Limits = new Limits(0.0, 0.0, 0.0)
var avgci90: Limits = new Limits(0.0, 0.0, 0.0)
var avgci95: Limits = new Limits(0.0, 0.0, 0.0)
var avgci99: Limits = new Limits(0.0, 0.0, 0.0)

 for(ci <- arrCIRatio){  
    ci85 = ci.c85
    ci90 = ci.c90
    ci95 = ci.c95
    ci99 = ci.c99

    avgci85 = new Limits(avgci85.lowerLimit + ci85.lowerLimit, avgci85.upperLimit + ci85.upperLimit, 0.85) 
    avgci90 = new Limits(avgci90.lowerLimit + ci90.lowerLimit, avgci90.upperLimit + ci85.upperLimit, 0.90) 
    avgci95 = new Limits(avgci95.lowerLimit + ci95.lowerLimit, avgci95.upperLimit + ci85.upperLimit, 0.95) 
    avgci99 = new Limits(avgci99.lowerLimit + ci99.lowerLimit, avgci99.upperLimit + ci85.upperLimit, 0.99) 
}

Но я должен сделать один и тот же процесс как минимум для 10 переменных и всех CI внутри массива.Таким образом, в конце для 1 переменной это будет трехмерный массив 10000 x 4 x 3 .Я не знаю, как суммировать все переменные внутри этого массива, например, суммировать все нижний предел из ci85 в массиве.Было бы здорово, если бы кто-то мог помочь с этим.

1 Ответ

3 голосов
/ 15 мая 2019

Может быть, просто создать метод / оператор для ваших CI и Limits , который позволил бы вам объединить два экземпляра? Примерно так:

case class Limits(lowerLimit: Double, upperLimit: Double, confidenceInterval: Double) {
  // operator |+| would allow us to combine two limits
  def |+|(l: Limits): Limits = Limits(l.lowerLimit + lowerLimit, l.upperLimit + upperLimit, confidenceInterval)
 // I don't know what should be done in case of attempt of combining two limits with different confidenceInterval. 
 // Maybe it's a sign that every kind of Limits should be separate case class extending the common trait
}

object Limits {
  val Zero = new Limits(0,0,0) //zero element for convienience
}

case class CI(c85: Limits, c90: Limits, c95: Limits, c99: Limits) {
  //same operator for CI, we use |+| from Limits to combine them
  def |+|(c: CI): CI = CI(c.c85 |+| c85, c.c90 |+| c90, c.c95 |+| c95, c.c99 |+| c99)
}

object CI {
  val Zero = new CI(Limits.Zero, Limits.Zero, Limits.Zero, Limits.Zero)
}

Тогда вы сможете легко сложить CI :

arrCIRatio.fold(CI.Zero)(_ |+| _)

То, что мы сделали, называется моноид . Вместо реализации | + | и Zero внутри классов case вы можете реализовать его с использованием классов типов (как описано в статье).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...