Scala多元数组和

时间:2019-05-15 14:01:40

标签: scala confidence-interval

我正在使用自举法对多个变量计算某些比率的置信区间,并且每个变量具有不同的置信区间。

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)
}

循环结束后,我想对所有 ci85,ci89,ci95,ci99的CI数组中每个上限和下限取平均值。

我可以使用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 的3维数组。 我不知道如何将数组中的所有变量求和,例如汇总数组中所有 ci85 下限。如果有人可以提供帮助,那就太好了。

1 个答案:

答案 0 :(得分:3)

也许只是为您的 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)(_ |+| _)

我们所做的称为monoid。代替在案例类内部实现 | + | Zero ,您可以使用类型类(如本文所述)来实现它。