Summing rows by index using a drive

Is it possible to sum rows or columns across multiple indices without using a for loop?

I have an nn matrix, M , which represents a match of dictionary terms, where n is the length of the dictionary.

I also have an nn logical mask, L , which represents pairs of dictionaries, where the pair has the form (singular, plural). For example, in the pseudocode L('octopus', 'octopuses') = True

I want to add entries in M for any pair that contains the plural for writing for a pair that contains the corresponding singular. For example, in the pseudocode M_sum('octopus', 'swim') = M('octopus', 'swim') + M('octopuses', 'swim') ;

To illustrate what I have tried so far, let me use the following toy data.

 vocabulary = {'octopus', 'octopuses', 'swim'}; % The co-occurrence matrix is symmetric M = [0, 9, 3; 9, 0, 1; 3, 1, 0;]; % This example has only one plural singular pair L = [0, 1, 0; 0, 0, 0; 0, 0, 0;]; 

To find a singular multiple match, I can use find

 [singular, plural] = find(L == 1); 

If for each singular there is only one plural, then summing rows or columns is simple

 M_sum = M; M_sum(singular, :) = M_sum(singular, :) + M(plural, :); M_sum(:, singular) = M_sum(:, singular) + M(:, plural); % Remove diagonal entries M_sum(eye(size(M))==1) = 0; 

However, if there are several plurals that correspond to one singular, this approach cannot be used.

For instance,

 vocabulary = {'octopus', 'octopuses', 'octopi', 'swim'}; M = [0, 9, 5, 3; 9, 0, 7, 1; 5, 7, 0, 11; 3, 1, 11, 0;]; L = [0, 1, 1, 0; 0, 0, 0, 0; 0, 0, 0, 0; 0, 0, 0, 0;]; 

The correct answer should be

 M_sum = [0, 16, 12, 15; 16, 0, 7, 1; 12, 7, 0, 11; 15, 1, 11, 0;]; 

But using the above method returns

 M_sum = [0, 16, 5, 14; 16, 0, 7, 1; 5, 7, 0, 11; 14, 1, 11, 0;]; 

Basically, M_sum(singular, :) = M_sum(singular, :) + M(plural, :); uses only the latest plural index.

I think I need to use accumarray here, but I am having trouble formulating the correct instruction, because I have two indexes, plural and singular . If accumarray not the right approach, other solutions are also welcome.

+2
source share
1 answer

Try the following:

 M_sum = (L + eye(size(L,1)))*M; M_sum = triu(M_sum, 1); M_sum = M_sum + M_sum.'; 

This works because you already have the matrix L , so matrix multiplication can be used to select and sum the rows of M


Using accumarray here will have two drawbacks:

  • You need to use find to convert L to indexes, which will be used as the first input for accumarray . So one more step.
  • accumarray can only sum numbers, not row vectors (the second input can only be a column vector, not a matrix). Therefore, you will need to call accumarray once per column M
+4
source

All Articles