0

I have a matrix (population, with 8 columns and 100 rows) of positive and negative numbers.

I want to create a matrix where each row has 8 real numbers which satisfy:

  • All numbers are in the range [0,1]
  • The sum of numbers in each row should be equal to 1

I wrote the code below. I tried to normalize the number in the rows but it doesn't work because the result contains negative numbers.

population(:,1:8) = bsxfun(@rdivide,population(:,1:8).',sum(population(:,1:8).')).';

How can I fix this?


For example, the input [1 -2 3] should give the output [0.375 0 0.625]

Wolfie
  • 27,562
  • 7
  • 28
  • 55
hsi
  • 97
  • 1
  • 11
  • If you want a uniform distribution (restricted to sum 1), see [here](https://stackoverflow.com/q/8064629/2586922) – Luis Mendo Oct 24 '17 at 15:21

2 Answers2

1

You simply need to subtract the row-wise minimum (regardless whether it's negative) and divide by the row-wise sum. You can use the dim argument of min and sum to specify the value should be taken row-wise...

% Get positive values by subtractive the row-wise minimum
pos = bsxfun(@minus, data, min(data, [], 2));
% Normalise by dividing by the row-wise sum
normalized = bsxfun(@rdivide, pos, sum(pos,2));

For example:

data = [5     6     0
        6     3     2
       -1    -2     6];
pos = bsxfun(@minus, data, min(data, [], 2))
>> pos = 
      [5    6    0
       4    1    0
       1    0    8]
normalized = bsxfun(@rdivide, pos, sum(pos,2)) 
>> normalized = 
     [0.4545    0.5455         0
      0.8000    0.2000         0
      0.1111         0    0.8889]

Note: from MATLAB 2016b, the new implicit expansion methods mean you don't need bsxfun, and can simply do

pos = data - min(data, [], 2);
normalized = pos ./ sum(pos, 2);
Wolfie
  • 27,562
  • 7
  • 28
  • 55
0

you can do it likes the following:

col_size = size(matrix,2);
matrix = matrix - repmat(min(matrix.').', 1, col_size); % minus minimum
normal_matrix = matrix./repmat(sum(matrix, 2), 1, col_size);

using sum(matrix, 2) to get sum of rows. Then apply repmat to repeat this columnar matrix to get a matrix with size of the original matrix. Then divide the original matrix with the repeated columnar matrix.

OmG
  • 18,337
  • 10
  • 57
  • 90
  • @hsi I don't think so. Be more precise. – OmG Oct 24 '17 at 14:00
  • sorry that comment was for lbezito ,not for you. – hsi Oct 24 '17 at 14:02
  • i have the matrix with negative number. i want to normalize that matrix.result should have positive number. i think your suggest create Repetitious culumn of data? is not? – hsi Oct 24 '17 at 14:12
  • For Matlab 2016b and up, you can use arithmetic expand: `matrix./sum(matrix,2)` – Adiel Oct 24 '17 at 14:12
  • @hsi you have to give an explicit example for input and desired output – Adiel Oct 24 '17 at 14:14
  • i have a matrix . it is not normalize. some of this data is negative. it is the input of code. each row of this matrix should have positive normalize number in [0,1]. and the sum of number in each row should be equal to 1.it is the out put. – hsi Oct 24 '17 at 14:22
  • This is not an example. I don't know what you mean by normalizing negative and positive values... Look at @wolfie's comment – Adiel Oct 24 '17 at 14:31
  • input have negative numbers .is your suggest code result in positive numbers? i want to have positive number in result. – hsi Oct 24 '17 at 14:32
  • example for one row of matrix =>input: 1 -2 3 , output : 0.375 0 0.625 – hsi Oct 24 '17 at 14:41
  • what would be the result of [-3 5] and [0 0 0] ? – Leander Moesinger Oct 24 '17 at 15:08
  • i use this code instead of the code in question but it have sum not equal to 1.my code is:population = zeros(100,8); population = rand(100,8); for ii=1:size(population,1) population(ii,:) = (population(ii,:) - min(population(ii,:))) / ( max(population(ii,:)) - min(population(ii,:)))/(sum(population(ii,:))); end – hsi Oct 24 '17 at 15:37
  • @hsi again. my code is different. You've written answer of Ibezito. – OmG Oct 24 '17 at 15:59