我可以在不使用for循环的情况下对多个索引上的行或列求和吗?
我有一个n×n矩阵M
,它代表词汇术语的共同出现,其中n是词汇表的长度。
我还有一个n×n逻辑掩码L
,它表示对中具有形式(单数,复数)的词汇对。例如,在伪代码中,L('octopus', 'octopuses') = True
我想在M
中添加条目,以包含对包含相应单数的对的复数的任何对。例如,在伪代码中,M_sum('octopus', 'swim') = M('octopus', 'swim') + M('octopuses', 'swim')
;
为了说明我到目前为止所尝试的内容,请使用以下玩具数据。
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;];
要找到单数到复数的对应关系,我可以使用find
[singular, plural] = find(L == 1);
如果每个单数只有一个复数,则对行或列求和很简单
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;
但是,如果有多个复数对应一个单数,则不能使用此方法。
例如,
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;];
正确的答案应该是
M_sum = [0, 16, 12, 15;
16, 0, 7, 1;
12, 7, 0, 11;
15, 1, 11, 0;];
但使用上述方法返回
M_sum = [0, 16, 5, 14;
16, 0, 7, 1;
5, 7, 0, 11;
14, 1, 11, 0;];
基本上,M_sum(singular, :) = M_sum(singular, :) + M(plural, :);
仅使用最后一个plural
索引。
我认为我需要在这里使用accumarray
,但我在制定正确的陈述方面遇到了一些麻烦,因为我有两个索引plural
和singular
。如果accumarray
不是正确的方法,也欢迎其他解决方案。
答案 0 :(得分:4)
试试这个:
M_sum = (L + eye(size(L,1)))*M;
M_sum = triu(M_sum, 1);
M_sum = M_sum + M_sum.';
这是因为你已经有了矩阵L
,所以矩阵乘法可以用来选择M
的行并加总。
在这里使用accumarray
会有两个缺点:
find
将L
转换为索引,以用作accumarray
的第一个输入。再迈一步了。accumarray
只能汇总数字,而不是行向量(其第二个输入只能是列向量,而不是矩阵)。因此,您需要在accumarray
每列调用一次M
。