简体   繁体   English

在矩阵的每一行中找到1的列索引

[英]Finding the column index for the 1 in each row of a matrix

I have the following matrix in Matlab: 我在Matlab中有以下矩阵:

M = [0 0 1
     1 0 0
     0 1 0
     1 0 0
     0 0 1];

Each row has exactly one 1. How can I (without looping) determine a column vector so that the first element is a 2 if there is a 1 in the second column, the second element is a 3 for a one in the third column etc.? 每行正好有一个1。如何确定列向量,因此如果第二列中的第一个元素为1,则第一个元素为2,第三列中的第一个元素为3,等等。 。? The above example should turn into: 上面的例子应该变成:

M = [ 3
      1
      2
      1
      3];

You can actually solve this with simple matrix multiplication. 实际上,您可以使用简单的矩阵乘法来解决此问题。

result = M * (1:size(M, 2)).';

     3
     1
     2
     1
     3

This works by multiplying your M x 3 matrix with a 3 x 1 array where the elements of the 3x1 are simply [1; 2; 3] 这是通过将M x 3矩阵乘以3 x 1数组(其中3x1的元素只是[1; 2; 3] [1; 2; 3] [1; 2; 3] . [1; 2; 3] Briefly, for each row of M , element-wise multiplication is performed with the 3 x 1 array. 简而言之,对于M每一行,使用3 x 1数组执行逐元素乘法。 Only the 1's in the row of M will yield anything in the result. M的行中只有1会产生任何结果。 Then the result of this element-wise multiplication is summed. 然后,将按元素相乘的结果相加。 Because you only have one "1" per row, the result is going to be the column index where that 1 is located. 因为每行只有一个“ 1”,所以结果将是该1所在的列索引。

So for example for the first row of M . 因此,例如对于M的第一行。

element_wise_multiplication = [0 0 1] .* [1 2 3]

    [0, 0, 3]

sum(element_wise_multiplication)

    3

Update 更新资料

Based on the solutions provided by @reyryeng and @Luis below, I decided to run a comparison to see how the performance of the various methods compared. 根据下面@reyryeng@Luis提供的解决方案,我决定进行比较,以比较各种方法的性能。

To setup the test matrix ( M ) I created a matrix of the form specified in the original question and varied the number of rows. 为了设置测试矩阵( M ),我创建了原始问题中指定形式的矩阵,并更改了行数。 Which column had the 1 was chosen randomly using randi([1 nCols], size(M, 1)) . 使用randi([1 nCols], size(M, 1))随机选择哪一列具有1。 Execution times were analyzed using timeit . 使用timeit分析执行时间。

When run using M of type double (MATLAB's default) you get the following execution times. 使用double类型的M (MATLAB的默认值)运行时,将获得以下执行时间。

在此处输入图片说明

If M is a logical , then the matrix multiplication takes a hit due to the fact that it has to be converted to a numerical type prior to matrix multiplication, whereas the other two have a bit of a performance improvement. 如果Mlogical ,则由于矩阵乘法必须在矩阵乘法之前转换为数字类型这一事实而大受打击,而其他两个则在性能上有所提高。

在此处输入图片说明

Here is the test code that I used. 这是我使用的测试代码。

sizes = round(linspace(100, 100000, 100));
times = zeros(numel(sizes), 3);

for k = 1:numel(sizes)
    M = generateM(sizes(k));
    times(k,1) = timeit(@()M * (1:size(M, 2)).');
    M = generateM(sizes(k));
    times(k,2) = timeit(@()max(M, [], 2), 2);
    M = generateM(sizes(k));
    times(k,3) = timeit(@()find(M.'), 2);
end

figure
plot(range, times / 1000);
legend({'Multiplication', 'Max', 'Find'})
xlabel('Number of rows in M')
ylabel('Execution Time (ms)')

function M = generateM(nRows)
    M = zeros(nRows, 3);
    col = randi([1 size(M, 2)], 1, size(M, 1));
    M(sub2ind(size(M), 1:numel(col), col)) = 1;
end

You can also abuse find and observe the row positions of the transpose of M . 您还可以滥用find和观察M的转置行的位置。 You have to transpose the matrix first as find operates in column major order: 您必须先转置矩阵,因为find按列主要顺序进行操作:

M = [0 0 1
     1 0 0
     0 1 0
     1 0 0
     0 0 1];

[out,~] = find(M.');

Not sure if this is faster than matrix multiplication though. 虽然不确定这是否比矩阵乘法快。

Yet another approach: use the second output of max : 还有另一种方法:使用max的第二个输出:

[~, result] = max(M.', [], 1);

Or, as suggested by @rayryeng , use max along the second dimension instead of transposing M : 或者,如@rayryeng所建议,在第二维上使用max而不是转置M

[~, result] = max(M, [], 2);

For 对于

M = [0 0 1
     1 0 0
     0 1 0
     1 0 0
     0 0 1];

this gives 这给

result =
     3     1     2     1     3

If M contains more than one 1 in a given row, this will give the index of the first such 1 . 如果M在给定的行中包含多个1 ,则将给出第一个此类1的索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM