Scala 多元数组求和
Scala multivariate array sum
我正在使用多变量自举法计算某些比率的置信区间,每个变量都有不同的置信区间。
case class Limits(lowerLimit: Double, upperLimit: Double, confidenceInterval: Double)
case class CI(c85: Limits, c90: Limits, c95: Limits, c99: Limits)
为了bootstrapping,我运行循环了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的所有下限求和。如果有人能帮忙解决就好了。
也许只需为您的 CI 和 Limits 创建 method/operator,这样您就可以合并两个实例?类似的东西:
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。您可以使用 type类 实现它,而不是在 case 类 中实现 |+| 和 Zero (如文章)。
我正在使用多变量自举法计算某些比率的置信区间,每个变量都有不同的置信区间。
case class Limits(lowerLimit: Double, upperLimit: Double, confidenceInterval: Double)
case class CI(c85: Limits, c90: Limits, c95: Limits, c99: Limits)
为了bootstrapping,我运行循环了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的所有下限求和。如果有人能帮忙解决就好了。
也许只需为您的 CI 和 Limits 创建 method/operator,这样您就可以合并两个实例?类似的东西:
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。您可以使用 type类 实现它,而不是在 case 类 中实现 |+| 和 Zero (如文章)。