I am getting a dimension error while using math.subtract()
const X = [[1, 2], [3, 4], [5, 6]]
const A = math.transpose(X);
// A = [ [ 1, 3, 5 ], [ 2, 4, 6 ] ]
const M = math.mean(A, 1);
// M = [ 3, 4 ]
const C = math.subtract(X, M);
Running the code raises the below error
....mathjs/lib/function/arithmetic/subtract.js:172
throw new DimensionError(xsize.length, ysize.length);
I believe math.subtract(X, M) should return
[[-2., -2.],
[ 0., 0.],
[ 2., 2.]]
same goes for math.sum math.multiply
In the meantime, I will write an extension method to achieve my goal
Temporary extension method that I am using:
/**
* Subtracts two matrices
* @param X
* @param y
*/
const subtract = (X, y) => {
const _X = _.clone(X);
for (let rowIndex = 0; rowIndex < _X.length; rowIndex++) {
const row = X[rowIndex];
for (let colIndex = 0; colIndex < row.length; colIndex++) {
const column = row[colIndex];
// Supports y.length === 1 or y.length === row.length
if (y.length === 1) {
const subs = y[0];
_X[rowIndex][colIndex] = column - subs;
} else if (y.length === row.length) {
const subs = y[colIndex];
_X[rowIndex][colIndex] = column - subs;
} else {
throw Error(`Dimension of y ${y.length} and row ${row.length} are not compatible`);
}
}
}
return _X;
}
Yes, that can be a useful extension. Right now math.subtract, math.add, etc simply do element-wise subtraction/addition. Allowing to subtract a vector row-wise from a matrix is something you can do in Matlab and Octave.
I will change the title of this topic a bit.
Anyone interested in implementing this feature?
Once I finish the getMatrixDataType pull request, I am happy to implement it =). Sorry I was busy for the last few days =)...
:+1: thanks for the offer. and for keeping focus :)
We can consider two cases in this regard, as noted by @alvinhui in #1228:
Case 1:
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; const b= [[9], [8], [7]]; math.subtract(a, b); // should be [[-8, -7, -6], [-4, -3, -2], [ 0, 1, 2]]Case 2
const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; const b= [9, 8, 7]; math.subtract(a, b); // should be [[-8, -6, -4], [-5, -3, -1], [-2, 0, 2]]This behavior is similar to subtraction between Python arrays:
a = np.array([[1,2,3], [4,5,6], [7,8,9]]) b = np.array([9,8,7]) c = [[9], [8], [7]]; a - b a - c
This could definitely be useful in some cases. But I suggest that there should be a way to turn it off.
Example: I mainly use MathJS for math webapps to be used by high-school and undergraduate students. I generally want students to think that adding matrix + vector is not valid. Great, MathJS throws a useful error!
I could be one of a small minority, but I would guess that MathJS's current behavior is useful to other people.
(Admittedly, if people like me want this error, it's not too hard to do our own validation. But that makes upgrading harder.)
Incidentally, numpy calls this broadcasting. (Although, Numpy's broadcasting is more general.)
Edit: To be clear, doing my own validation really is not a big deal. Just something to consider :)
Thanks for the inputs guys =)
Thanks for sharing your thoughts @ChristopherChudzicki. Very good point to weight convenience against more explicit notations preventing you from accidental mistakes. We could also think about a solution where we have separate, explicit functions (like subtractVector(matrix, vector)) to do operations on matrices and vectors, or pass an extra option to these functions
(like subtract(matrix, vector, { broadcast: true })
or subtract(matrix, vector, { rowWise: true })).
Just thinking aloud here :)
That said, it occurs to me that allowing matrix + row or matrix + vector consistent with how MathJS handles matrix + scalar. What I mean is, in the matrix+scalar case MathJS already does not demand strict shape-matching.
So maybe this is the "right" behavior.
Yes that's true.
I'm just exploring different options, not sure yet what solution would best serve the audience of mathjs.
Any progress on this? Am getting into mathjs as a numpy replacement in the browser for implementing ML/AI stuffs. Broadcasting is a verrry handy feature that makes a lot of learning algorithms a bit simpler to implement. Happy to pitch in.
Also might add the word "Broadcasting" to the title for the numpy folks looking for help on this. I'd imagine they'll become a larger and larger part of your target audience, if they aren't currently.
@chivington thanks for your input. There is no progress on this feature so far. I've marked the issue with a label "help wanted", now.
Anyone interested in implementing this feature?
Hello!! My case is similar to @chivington. I am getting into machine learning on the web and I need an alternative for NumPy. The above feature (broadcasting) is a real help for easier manipulation of matrices. Is there any way I can implement it alone in the meantime until it is a mainstream MathJS function (if it will ever be). 馃槂
Is there any way I can implement it alone in the meantime until it is a mainstream MathJS function (if it will ever be).
The solution would be to implement your own version of all operators/functions like subtract, add, etc, like Jason suggests in https://github.com/josdejong/mathjs/issues/1165#issuecomment-404493249.