Let's say I have a Nx3 matrix M.
Consider, for example, a function Map(v) that receives as input a 1x3 array and returns a double.
How can I sort the rows of M so that the rows with smallest Map should come first?
That is, the row i should be the first if Map(M(i,:)) ≤ Map(M(j,:)) for all 1 ≤ j ≤ N and j ≠ i ?
example:
M = |1 2 3|
|4 5 6|
|7 8 9|
Map(v){
if (v(1) == 1 && v(2) == 2 && v(3) == 3) return 2
if (v(1) == 4 && v(2) == 5 && v(3) == 6) return 3
if (v(1) == 7 && v(2) == 8 && v(3) == 9) return 1
}
So the sorting should leave M like this:
M = |7 8 9|
|1 2 3|
|4 5 6|
% initialize an N-by-3 matrix where N=10...
M = [
1 0 3;
4 2 2;
0 1 0;
7 5 6;
3 3 8;
2 1 4;
0 0 6;
3 1 2;
5 0 0;
1 6 2
];
% sum its rows...
M_sum = sum(M,2);
% sort the vector of sums in ascending order...
[~,idx] = sort(M_sum);
% reorder the matrix rows based on the sorting result...
M = M(idx,:);
Related
I'm interested in the value of result that is in the same row as the min value of each column (and I have many columns, so I would like to loop over them, or do rowfun but I do not know how to get 'result' then).
Table A
+----+------+------+----+------+------+--------+
| x1 | x2 | x3 | x4 | x5 | x6 | result |
+----+------+------+----+------+------+--------+
| 1 | 4 | 10 | 3 | 12 | 2 | 8 |
| 10 | 2 | 8 | 1 | 12 | 3 | 10 |
| 5 | 10 | 5 | 4 | 2 | 10 | 12 |
+----+------+------+----+------+------+--------+
Solution
8 10 12 10 12 8
I know that I can apply rowfun, but then I don't know how to get result.
And then, I can do this, but cannot loop over all the columns:
A(cell2mat(A.x1) == min(cell2mat(A.x1)), 7)
and I have tried several ways of making this into a variable but I can't make it work, so that:
A(cell2mat(variable) == min(cell2mat(variable)), 7)
Thank you!
Assuming your data is homogeneous you can use table2array and the second output of min to index your results:
% Set up table
x1 = [1 10 5];
x2 = [4 2 10];
x3 = [10 8 5];
x4 = [3 1 4];
x5 = [12 12 2];
x6 = [2 3 10];
result = [8 10 12];
t = table(x1.', x2.', x3.', x4.', x5.', x6.', result.', ...
'VariableNames', {'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'result'});
% Convert
A = table2array(t);
% When passed a matrix, min finds minimum of each column by default
% Exclude the results column, assumed to be the last
[~, minrow] = min(A(:, 1:end-1));
solution = t.result(minrow)'
Which returns:
solution =
8 10 12 10 12 8
From the documentation for min:
M = min(A) returns the smallest elements of A.
<snip>
If A is a matrix, then min(A) is a row vector containing the minimum value of each column.
I have a matrix A in Matlab of dimension m x 3, e.g. m=18
A=[ 2| 1 1;
3| 1 2;
-8| 1 3;
-------
-5| 1 1;
2| 1 2;
6| 1 3;
-------
7| 2 1;
3| 2 2;
1| 2 3;
5| 2 4;
-------
3| 2 1;
-8| 2 2;
1| 2 3;
0| 2 4;
-------
1| 2 1;
2| 2 2;
7| 2 3;
9| 2 4]
The characteristics of A are the following:
It is composed by t submatrices. In the example t=5.
Each submatrix t has dimension b x 3 with b<=m and b can take any value in {3,4,5,...,m} (clearly, in a way such that the sum of all rows is m). In the example, the first and the second submatrices have dimension 3 x 3, the last three submatrices have dimension 4 x 3.
All submatrices of the same dimension are stacked one after the other. In the example, firstly we have the submatrices 3 x 3 and then the submatrices 4 x 3.
I want to compute the vector B of dimension f x 1 where f=size(unique(A(:,2:end),'rows','stable'),1), (in the example f=7), such that B(i,1) is obtained by summing the elements j of A(:,1) having A(j,2:end) equal to the i-th row of unique(A(:,2:end),'rows','stable'), i.e.
B=[2-5;
3+2;
-8+6
7+3+1;
3-8+2;
1+1+7;
5+0+9]
Use the third output of unique when examining A over the rows and with the 'stable' flag, then use this as input into accumarray. The third output assigns a unique ID for each unique occurrence of a row vector seen in your matrix A, which is very suitable for use in accumarray:
[~,~,f] = unique(A(:,2:end), 'rows', 'stable');
B = accumarray(f, A(:,1));
We get:
B =
-3 %// 2-5
5 %// 3+2
-2 %// -8+6
11 %// 7+3+1
-3 %// 3-8+2
9 %// 1+1+7
14 %// 5+0+9
Not sure how to explain it so here it goes as an example:
A=[1 0 0 1 4 4 4 4
0 0 0 0 2 3 2 2
0 0 0 0 0 0 0 1
2 3 4 5 2 3 4 1 ]
result:
b=[ 1 1 13 12
5 9 5 6];
Each of the elements is computed by adding a N size submatrix inside the original, in this case N=2.
so b(1,1) is A(1,1)+A(1,2)+A(2,1)+A(2,2), and b(1,4) is A(1,7)+A(2,7)+A(1,8)+A(2,8).
Visually and more clearly:
A=[|1 0| 0 1| 4 4| 4 4|
|0 0| 0 0| 2 3| 2 2|
____________________
|0 0| 0 0| 0 0| 0 1|
|2 3| 4 5| 2 3| 4 1| ]
b is the sum of the elements on those squares, in this example of size 2.
I can imagine how to make it with loops, but its just feels vectorizable. Any ideas of how it could be done?
Assume that the matrix A has sizes that are multipliers of N.
If you have the Image processing toolbox blockproc could be an option as well:
B = blockproc(A,[2 2],#(x) sum(x.data(:)))
Method 1:
Using mat2cell and cellfun
n = 2;
AC = mat2cell(A,repmat(n,size(A,1)/n,1),repmat(n,size(A,2)/n,1));
out = cellfun(#(x) sum(x(:)), AC)
Method 2:
Using permute and reshape
n = 2;
[rows,cols] = size(A);
out = reshape(sum(sum(permute(reshape(A,n,rows/n,n,[]),[1 3 2 4]))),rows/n,[]);
PS: Here is a close question related to this one, which you might find useful. That question is to find mean while this one is to find sum.
Here are two alternative methods:
Method #1 - im2col
Another method using the image processing toolbox is to use im2col with the distinct flag and sum over all of the resulting columns. You would then need to reshape the matrix back to the right size:
n = 2;
B = im2col(A, [n n], 'distinct');
C = reshape(sum(B, 1), size(A,1)/n, size(A,2)/n);
We get for C:
>> C
C =
1 1 13 12
5 9 5 6
Method #2 - accumarray and kron
We can generate an index matrix with kron which we can use as bins into accumarray and invoke sum as the custom function. We would again have to reshape the matrix back to the right size:
n = 2;
M = reshape(1:prod([size(A,1)/n, size(A,2)/n]), size(A,1)/n, size(A,2)/n);
ind = kron(M, ones(n));
C = reshape(accumarray(ind(:), A(:), [], #sum), size(A,1)/n, size(A,2)/n);
Again we get for C:
C =
1 1 13 12
5 9 5 6
Element by element, I want to concatenate binary values from different matrices to one matrix.
For example,
|1 0 0| |0 1 0| |10 01 00|
|0 1 1| |1 1 0| = |01 11 10|
|1 0 1| |0 0 1| |10 00 11|
How can this be done?
I would store the output matrix as a decimal matrix and convert to binary strings when accessing elements.
To concatenate the elements, treat each input matrix as a binary digit
A1 = [1 0 0; 0 1 1; 1 0 1];
A2 = [0 1 0; 1 1 0; 0 0 1];
output = A1 * 2^1 + A2 * 2^0;
output_str = arrayfun(#dec2bin, output, 'UniformOutput', false);
output will be a double matrix
[2, 1, 0;
1, 3, 2;
2, 0, 3]
output_str will be a cell array of strings
['10', '1', '0';
'1', '11', '10';
'10', '0', '11']
Here is one alternative without bin2dec or dec2bin conversion
out = arrayfun(#(x,y) strcat(num2str(x),num2str(y)),A1,A2,'Uni',0);
Input:
A1 = [1 0 0; 0 1 1; 1 0 1];
A2 = [0 1 0; 1 1 0; 0 0 1];
output:
>> out
out =
'10' '01' '00'
'01' '11' '10'
'10' '00' '11'
If you want it as numeric instead of string, you might do this:
outp = cellfun(#(x) str2double(x), out);
output:
>> outp
outp =
10 1 0
1 11 10
10 0 11
I'm sorry if this is a stupid question but I just can't find the answer I need.
I have the following matrix:-
A |6 6 0|
|9 0 0|
Each column represents co-ordinates on a grid.
Now to find the inverse of "A" I need to create this into a 3x3 square matrix, to do this I add 001 as the 3rd row...
B |6 6 0|
|9 0 0|
|0 0 1|
I do this simply because it is what I have seen in the online examples.
My question is, what is the method to calculate/add the 3rd row of a 2x3 matrix in this situation?
It is not possible to take the inverse of a matrix that is not squared..
I assume that would like to just extend the matrix in order to make i squared, the reason why you use the [0 0 1] is to make the matrix consistent..
Actually you matrix represent two equations with three variables..
A:
6*x_1 + 6*x_2 + 0*x_3 = 0
9*x_1 + 0*x_2 + 0*x_3 = 0
this is not consistent
but by adding the last row you get
B:
6*x_1 + 6*x_2 + 0*x_3 = 0
9*x_1 + 0*x_2 + 0*x_3 = 0
0*x_1 + 0*x_2 + 1*x_3 = 0
this matrix exists on echelon form
[1 0 0]
[0 1 0]
[0 0 1]
so by adding the last row you are not changing the matrix
you would properly get same result just by reduce it to
[6 6]
[9 0]
Here is a simple way to do it:
s = size(A);
B = eye(max(s));
B(1:s(1),1:s(2)) = A