Reputation: 447
I have several matrices, each with the same number of columns but with varying row sizes. Each matrix contains both positive and negative values. For grouping sake (because there are lots of matrices), each matrix is stored in a 2D cell array. A small example:
Matrix1:
C1 C2 C3
Val1 6 7 1
Val2 3 9 -7
Val3 -12 -22 -4
Matrix2:
C1 C2 C3
Val1 5 19 -2
Val2 4 21 9
Val3 -1 3 11
Val4 -30 13 7
Val5 3 -4 10
matrixStore{1,1} = Matrix1
matrixStore{1,2} = Matrix2
I am trying to normalise the values to a -1 to 1 range, in a column-wise, across-matrix manner. So, using the example, I get max and min values for each column and put them in two vectors:
% C1: Max = 6, Min = -30
% C2: Max = 21, Min = -22
% C3: Max = 11, Min = -7
maxVals = [6, 21, 11];
minVals = [-30, -22, -7];
How do I now apply the max and min values to normalise each column for all matrices?
I use the following code to get the max and min values:
maxColsBuilder = [];
minColsBuilder = [];
% Find the max values for each column in every matrix and stack them together
maxColValsFromCell = cellfun(@max, matrixStore(1,:), 'Uni', 0);
maxColMatrix = cell2mat(maxColValsFromCell');
maxColsBuilder = [maxColsBuilder, maxColMatrix'];
% Do the same for the min values
minColValsFromCell = cellfun(@min, matrixStore(1,:), 'Uni', 0);
minColMatrix = cell2mat(minColValsFromCell');
minColsBuilder = [minColsBuilder, minColMatrix'];
% Find the max values for each column
maxVals = (max( maxColsBuilder, [], 2 ))'
% Also find the min values for column
minVals = (min( minColsBuilder, [], 2 ))'
Can anyone help me use these vectors to normalise my data as required, please?
Upvotes: 1
Views: 200
Reputation: 447
Having done some extra searching, I found an answer by @rayryeng to this question (Min-max normalization of individual columns in a 2D matrix) that I modified to suit:
[unknown, matrices] = size(matrixStore);
for matrixIndex = 1:matrices
normMatrix = matrixStore{1, matrixIndex};
normMatrix = bsxfun(@minus, bsxfun(@rdivide, bsxfun(@minus, normMatrix, minVals), maxVals - minVals), 0.5) * 2
end;
This gives the same output as listed by @TomášKratochvíla in his answer.
When I apply both methods to some actual sample data, consisting of 6 matrices containing 12 columns and several thousand rows, I find the method using bsxfun
to be quicker.
If anyone has any further info regarding either answer, please feel free to add comments.
Upvotes: 1
Reputation: 763
The following code for each of your matrix from your matrixStore display the normalized version of the matrix:
[unknown, matrices] = size(matrixStore);
for matrixIndex = 1:matrices
[rows, columns] = size(matrixStore{1,matrixIndex});
normMatrix = matrixStore{1,matrixIndex};
for row = 1:rows;
for column = 1:columns;
normMatrix(row,column) = -1 + 2.*(matrixStore{1,matrixIndex}(row,column) - minVals(column))./(maxVals(column) - minVals(column));
end;
end;
normMatrix
end;
For the example you have provided:
normMatrix1 =
1.0000 0.3488 -0.1111
0.8333 0.4419 -1.0000
0 -1.0000 -0.6667
normMatrix2 =
0.9444 0.9070 -0.4444
0.8889 1.0000 0.7778
0.6111 0.1628 1.0000
-1.0000 0.6279 0.5556
0.8333 -0.1628 0.8889
If you have newer version of Matlab you can use normc function instead.
Upvotes: 0