humbleHacker
humbleHacker

Reputation: 447

How to normalise each corresponding column in several matrices to values between -1 and 1 in Matlab?

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

Answers (2)

humbleHacker
humbleHacker

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

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

Related Questions