如何根据某些条件替换Scala中的微风矩阵元素?

时间:2017-04-08 01:50:53

标签: scala apache-spark scala-breeze

我在Scala中使用2维Breeze矩阵。在某些时候,我必须对两个矩阵进行元素划分。分母矩阵中的某些元素可以为零,从而在结果中产生NaN。

我可以循环遍历矩阵尺寸,并使用> 0替换0.0s。

但对此有更简单或Scala惯用解决方案吗?

2 个答案:

答案 0 :(得分:6)

步骤一步:

  • 使用示例矩阵:

    val dm = DenseMatrix((1.0, 0.0, 3.0), (0.0, 5.0, 6.0))
    
  • 找出哪些元素等于0.0:

    dm :== 0.0
    
    breeze.linalg.DenseMatrix[Boolean] =
    false  true   false
    true   false  false
    
  • 切割矩阵:

    dm(dm :== 0.0)
    
    breeze.linalg.SliceVector[(Int, Int),Double] = breeze.linalg.SliceVector@2b
    
  • 使用切片矩阵进行替换:

    dm(dm :== 0.0) := 42.0
    
    breeze.linalg.Vector[Double] = breeze.linalg.SliceVector@2b
    
  • 检查矩阵:

    dm
    
    breeze.linalg.DenseMatrix[Double] =
    1.0   42.0  3.0
    42.0  5.0   6.0
    

答案 1 :(得分:0)

映射NaN比切片更快。

val matr = DenseMatrix((1.0, 0.0, 3.0), (0.0, 11.0, 12.0),
      (1.0, 2.0, 0.0))
val matr2 = DenseMatrix((3.0, 0.0, 1.0), (0.0, 12.0, 11.0),
      (2.0, 1.0, 0.0))

def time[R](block: => R): R = {
  val t0 = System.nanoTime()
  val result = block    // call-by-name
  val t1 = System.nanoTime()
  println("Elapsed time: " + (t1 - t0) + "ns")
  result
}

def replaceZeroes1(mat1: DenseMatrix[Double], mat2 DenseMatrix[Double], rep: Double) = {
   (mat1 /:/ mat2).map(x => if (x.isNaN()) rep else x)
}

def replaceZeroes2(mat1: DenseMatrix[Double], mat2 DenseMatrix[Double], rep: Double) = {
    mat1(mat1 :== 0.0) := rep
    mat2(mat2 :== 0.0) := 1
    mat1 /:/ mat2
}
time(println(replaceZeroes1(matr, matr2, 42.0)))
time(println(replaceZeroes2(matr, matr2, 42.0)))

产生:

0.3333333333333333  42.0                3.0                 
42.0                0.9166666666666666  1.0909090909090908  
0.5                 2.0                 42.0                
Elapsed time: 13087782ns
Replace Zero2
0.3333333333333333  42.0                3.0                 
42.0                0.9166666666666666  1.0909090909090908  
0.5                 2.0                 42.0                
Elapsed time: 16613179ns

绘制NaN既快捷又直接。即使从function2中删除第二个切片,它也更快。

注意:这没有在Spark中使用大型数据集进行过测试,只是轻而易举。在这种情况下,可能会有不同的时间(尽管我对此表示怀疑)。

奖金:

如果您只是想从具有任何一组值的矩阵中生成1s和0s矩阵(例如,从加权网络中生成非加权网络),我将使用:

(mat /:/ mat).map(x => if (x.isNaN()) 0.0 else x)