Matrix: Mat[T] #
import org.saddle._
import org.saddle.order._
A Mat[T]
represents a matrix of values. Internally it is stored as a single contiguous array in row-major order.
The row-major layout is compatible with EJML, a linear algebra library running on the JVM.
If you want to use a BLAS, you can take a look in saddle-linalg
.
Factories #
import org.saddle._
Mat(2,2, Array(1,2,3,4))
// res0: Mat[Int] = [2 x 2]
// 1 2
// 3 4
//
// all same:
Mat(Array(Array(1,3), Array(2,4)))
// res1: Mat[Int] = [2 x 2]
// 1 2
// 3 4
//
Mat(Vec(1,3), Vec(2,4))
// res2: Mat[Int] = [2 x 2]
// 1 2
// 3 4
//
Mat(Array(Vec(1,3), Vec(2,4)))
// res3: Mat[Int] = [2 x 2]
// 1 2
// 3 4
//
// identity matrix:
mat.ident(2)
// res4: Mat[Double] = [2 x 2]
// 1.0000 0.0000
// 0.0000 1.0000
//
// empty matrix:
Mat.empty[Double]
// res5: Mat[Double] = [0 x 0]
//
// zeros:
Mat[Int](2, 2)
// res6: Mat[Int] = [2 x 2]
// 0 0
// 0 0
//
Again, sometimes we want to create instances filled with random observations. As to Vec, we can do the following:
mat.rand(2,2)
// res7: Mat[Double] = [2 x 2]
// 0.4012 0.4034
// 0.0368 0.8055
//
mat.randp(2,2) // random positive doubles
// res8: Mat[Double] = [2 x 2]
// 0.9656 0.7263
// 0.7637 0.6760
// // random positive doubles
mat.randn(2,2) // random normally distributed doubles
// res9: Mat[Double] = [2 x 2]
// 1.2001 -1.5775
// -2.0597 -0.0178
// // random normally distributed doubles
mat.randn2(2,2,3,12) // random normally distributed with mean=3, stdev=12
// res10: Mat[Double] = [2 x 2]
// 1.2259 -1.5803
// 12.2012 -3.9029
//
There are a few other factory methods available:
mat.ones(2,2)
// res11: Mat[Double] = [2 x 2]
// 1.0000 1.0000
// 1.0000 1.0000
//
mat.zeros(2,2)
// res12: Mat[Double] = [2 x 2]
// 0.0000 0.0000
// 0.0000 0.0000
//
mat.diag(Vec(1,2))
// res13: Mat[Double] = [2 x 2]
// 1.0000 0.0000
// 0.0000 2.0000
//
Binary operations #
Let’s look at some basic operations with Mat. As with Vec, you may perform calculations on two Mat instances, or on a Mat and a scalar value.
import org.saddle.ops.BinOps._
// element-wise multiplication
Mat(2,2,Array(1,2,3,4)) * Mat(2,2,Array(4,1,2,3))
// res14: Mat[Int] = [2 x 2]
// 4 2
// 6 12
//
Linear algebra #
Matrix multiplication, matrix-vector multiplication or other linear algebra operatoins need saddle-linalg
, which depends on netlib-java. These work just on Mat[Double]
and Vec[Double]
.
import org.saddle.linalg._
// matrix multiplication
Mat(2,2,Array(1d,2d,3d,4d)) mm Mat(2,2,Array(4d,1d,2d,3d))
// res15: Mat[Double] = [2 x 2]
// 8.0000 7.0000
// 20.0000 15.0000
//
// matrix-vector multiplication
Mat(2,2,Array(1d,2d,3d,4d)) mv Vec(2d,1d)
// res16: Vec[Double] = [2 x 1]
// 4.0000
// 10.0000
//
// as expected
Mat(2,2,Array(1,2,3,4)) * 2
// res17: Mat[Int] = [2 x 2]
// 2 4
// 6 8
//
Mat(2,2,Array(1,2,3,4)) + 2
// res18: Mat[Int] = [2 x 2]
// 3 4
// 5 6
//
Mat(2,2,Array(1,2,3,4)) << 2
// res19: Mat[Int] = [2 x 2]
// 4 8
// 12 16
//
// etc...
// transpose
Mat(2,2,Array(1,2,3,4)).T
// res20: Mat[Int] = [2 x 2]
// 1 3
// 2 4
//
// properties of Mat
val m = Mat(2,2,Array(1,2,3,4))
// m: Mat[Int] = [2 x 2]
// 1 2
// 3 4
//
m.numRows
// res21: Int = 2
m.numCols
// res22: Int = 2
m.isSquare
// res23: Boolean = true
m.isEmpty
// res24: Boolean = false
Operations #
There are a few ways to extract values from a Mat.
m.at(0,1)
// res25: scalar.Scalar[Int] = Value(el = 2)
// be careful with this one!
m.raw(0,1)
// res26: Int = 2
m.takeRows(0)
// res27: Mat[Int] = [1 x 2]
// 1 2
//
m.withoutRows(0)
// res28: Mat[Int] = [1 x 2]
// 3 4
//
m.takeCols(0)
// res29: Mat[Int] = [2 x 1]
// 1
// 3
//
m.col(0)
// res30: Vec[Int] = [2 x 1]
// 1
// 3
//
m.row(0)
// res31: Vec[Int] = [2 x 1]
// 1
// 2
//
m.rows
// res32: IndexedSeq[Vec[Int]] = Vector(
// [2 x 1]
// 1
// 2
// ,
// [2 x 1]
// 3
// 4
//
// )
m.cols
// res33: IndexedSeq[Vec[Int]] = Vector(
// [2 x 1]
// 1
// 3
// ,
// [2 x 1]
// 2
// 4
//
// )
Some other interesting methods on Mat:
val m2 = Mat(2,2,Array(1,2,na[Int],4))
// m2: Mat[Int] = [2 x 2]
// 1 2
// NA 4
//
m2.rowsWithNA
// res34: Set[Int] = Set(1)
m2.dropRowsWithNA
// res35: Mat[Int] = [1 x 2]
// 1 2
//
m2.reshape(1,4)
// res36: Mat[Int] = [1 x 4]
// 1 2 NA 4
//
mat.rand(2,2).roundTo(2)
// res37: Mat[Double] = [2 x 2]
// 0.6100 0.5100
// 0.9500 0.5600
//