Suppose I have a 3x3 matrix
(def myMatrix (matrix (range 9) 3))
; A 3x3 matrix
; -------------
; 0.00e+00 1.00e+00 2.00e+00
; 3.00e+00 4.00e+00 5.00e+00
; 6.00e+00 7.00e+00 8.00e+00
I can use $ to get an element, say 2nd row 1st column
($ 1 0 myMatrix) ; --> 3
Is there any API method to quickly update an element and then return a matrix? e.g.
(update-matrix-by-element 2 1 myMatrix 4)
; A 3x3 matrix
; -------------
; 0.00e+00 1.00e+00 2.00e+00
; 4.00e+00 4.00e+00 5.00e+00
; 6.00e+00 7.00e+00 8.00e+00
The closest API methods I can find are bind-rows and bind-columns, and my current version of function using these two methods is
;note i j starts from 1 rather than 0
(defn update-matrix-by-element [i j myMatrix value]
(if (or (> i (count (trans myMatrix))) (> j (count myMatrix)) (< i 1) (< j 1) (not (integer? i)) (not (integer? j)))
myMatrix
(let [n (count myMatrix)
m (count (trans myMatrix))
rangeFn #(if (== %1 %2) %1 (range %1 %2 ))
m1 (if (== (dec i) 0) []
($ (rangeFn 0 (dec i)) :all myMatrix))
m2 (if (== i m) []
($ (rangeFn i m) :all myMatrix))
matrixFn #(if (matrix? % ) % [ %])
newRow (if (== (dec j) 0)
(bind-columns [value] (matrixFn ($ (dec i) (rangeFn j n ) myMatrix)))
(if (== j n )
(bind-columns (matrixFn ($ (dec i) (rangeFn 0 (dec j) ) myMatrix)) [value] )
(bind-columns (matrixFn ($ (dec i) (rangeFn 0 (dec j) ) myMatrix)) [value] (matrixFn ($ (dec i) (rangeFn j n ) myMatrix))))
)
]
; (prn " m1 " m1 ) (prn " m2 " m2 ) (prn " newrow " newRow)
(bind-rows m1 newRow m2))))
If you mean "quickly" in the sense of performance, then you may probably to look at core.matrix which is designed to support fast mutable matrix operations.
Example using the vectorz-clj implementation for core.matrix
:
(def M (matrix [[1 2] [3 4]]))
=> #<Matrix22 [[1.0,2.0][3.0,4.0]]>
(mset! M 0 0 10)
=> #<Matrix22 [[10.0,2.0][3.0,4.0]]>
(time (dotimes [i 1000000] (mset! M 0 0 i)))
"Elapsed time: 28.895842 msecs" ;; i.e. < 30ns per mset! operation
This will be much faster than anything which requires construction of a new mutable matrix, especially as the matrices get bigger / have higher dimensionality.
I'm working on making core.matrix
integrate neatly with Incanter, so you should be able to use core.matrix
matrices transparently within Incanter before too long.