我在Scala中使用2维Breeze矩阵。在某些时候,我必须对两个矩阵进行元素划分。分母矩阵中的某些元素可以为零,从而在结果中产生NaN。
我可以循环遍历矩阵尺寸,并使用> 0替换0.0s。
但对此有更简单或Scala惯用解决方案吗?
答案 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)