I have a matrix, for example
A = [ 1 2 3; 4 5 6; 7 8 9] ;
and a vector of size 1x3 which specifies which element in each row is the one I'm looking for - i.e. If
vector = [ 1 2 1 ]
then the desired output is
[ 1 5 7 ]
since 1 is the 1'st element in the 1'st row, 5 is the 2'nd in the 2'nd row, and 7 is the 1'st element in the 3'rd row.
How do I achieve this? Couldn't find a built in function to do this, which surprised me.
MATLAB provides the SUB2IND function to convert rows/columns subscripts to linear indices:
>> A = [1 2 3; 4 5 6; 7 8 9];
>> idx = sub2ind(size(A),1:3,[1 2 1]); %# rows: [1 2 3], cols: [1 2 1]
>> A(idx)
1 5 7
First of all, the indexes in Matlab go from top to bottom.
So in your case A[1] = 1 , A[2] = 4 , A[3] = 7
That said, it would be easier to work on A' , because its a bit more trivial.
B = A';
B((vector + [0:2].* 3))
It's a bit ugly, but diag(A(1:3,[1 2 1])) will do the trick.
Here's a variation of Yochai's answer but without the transpose (this is also basically what SUB2IND does in Amro's answer):
output = A((1:3)+3.*(vector-1));
Or for an array A of an arbitrary size:
nRows = size(A,1);
output = A((1:nRows)+nRows.*(vector-1));
Related
I have a column vector A (6x1) with values [6 3 10 4 2 8]'; and a matrix B (6x5) with values
B = [1 2 3 0 4 ;
3 7 8 5 0 ;
0 9 1 0 1 ;
5 0 3 1 2 ;
4 6 7 6 4 ;
3 1 2 7 3]
I want to make five matrices with size 6x2 using Matlab.
The first column is vector A
The second column is columns from B, like [A, B(first col)], [A, B(second col)]
First matrix is [6 1; 3 3; 10 0; 4 5; 2 4; 8 3];
2nd matrix is [6 2; 3 7; 10 9; 4 0; 2 6; 8 1]
... and so on
Any help I really appreciate it
You could use a loop
C = NaN( size(B,1), 2, size(B,2) );
for ii = 1:size(B,2)
C(:,:,ii) = [A, B(:,ii)];
end
This gives you a 3D array, where each slice in the 3rd dimension is a 6x2 matrix (for this example) as desired. You would access the nth slice with C(:,:,n).
You can do this slightly more concisely with arrayfun, but it's basically a loop in disguise
C = arrayfun( #(ii) [A, B(:,ii)], 1:size(B,2), 'uni', 0 );
C = cat(3, C{:} );
You could omit the cat function if you're happy with results in a cell array, where you access the nth matrix with C{n}.
You could first make a copy of the columns of A, then concatenate A and B, and reshape:
At = repmat(A, 1, size(B,2));
C = reshape([At;B], 6, 2, []);
Or oneliner:
C = reshape([repmat(A, 1, size(B,2));B], 6, 2, []);
Then retrieve your matrices with C(:,:,k)
you can use this
first_matrix=[A,B(:,1)];
second_matrix=[A,B(:,2)];
third_matrix=[A,B(:,3)];
... and so on
I am currently working on a stenography assignment on how to embed secret image to a cover image using Wang's algorithm. Basically i just want to change for eg:
3d matrix
A(:,:,1) = [5 7 8; 0 1 9; 4 3 6];
A(:,:,2) = [1 0 4; 3 5 6; 9 8 7];
A(:,:,3) = [7 9 3; 4 5 9; 1 9 9];
To
Str = '578019436104356987793459199'
and also vice-versa if anybody can help out.
Another way is to just use sprintf. You first need to transpose each slice independently, so the call to permute as per Ander's answer will get to that point. After you can just supply a single format string of %d (integer) and the actual permuted matrix and it will unroll all elements column-wise and concatenate all of the numbers together. The additional advantage is that you no longer need to assume that only one digit occupies each matrix element:
str = sprintf('%d', permute(A, [2 1 3]));
Example
>> str = sprintf('%d', permute(A, [2 1 3]))
str =
578019436104356987793459199
>> class(str)
ans =
char
However, to reconstruct the matrix, you will have to assume that there's one element per matrix. In this case, you could use the undocumented sprintfc function that can output one cell per character, then convert the characters to numbers with str2double. Finally, reshape your matrix and undo the transpose:
A2 = permute(reshape(str2double(sprintfc('%c', str)), size(A)), [2 1 3]);
Example
>> A2 = permute(reshape(str2double(sprintfc('%c', str)), size(A)), [2 1 3])
A2(:,:,1) =
5 7 8
0 1 9
4 3 6
A2(:,:,2) =
1 0 4
3 5 6
9 8 7
A2(:,:,3) =
7 9 3
4 5 9
1 9 9
Because of the order of the unrolling of MATLAB matrices, your problem is slightly less straightforward than it may seem. You need to use reshape and permute to make it work.
str=arrayfun(#num2str,reshape(permute(A,[2 1 3]),[],1,1)).';
A2=permute(reshape(arrayfun(#str2double,str),[size(A)]),[2 1 3]);
isequal(A2,A)
This of course assumes what #Sardar comments in your question: all numbers have single digits (i.e. are integers range 0-9)
I have a Matrix of size M by N in which each row has some zero entries. I want to create M row vectors such that each of the vector contains the non zero elements of each row. For example if I have the following Matrix
A=[0 0 0 5;0 0 4 6;0 1 2 3;9 10 2 3]
I want four different row vectors of the following form
[5]
[4 6]
[1 2 3]
[9 10 2 3]
This can be done with accumarray using an anonymous function as fourth input argument. To make sure that the results are in the same order as in A, the grouping values used as first input should be sorted. This requires using (a linearized version of) A transposed as second input.
ind = repmat((1:size(A,2)).',1,size(A,2)).';
B = A.';
result = accumarray(ind(:), B(:), [], #(x){nonzeros(x).'});
With A = [0 0 0 5; 0 0 4 6; 0 1 2 3; 9 10 2 3]; this gives
result{1} =
5
result{2} =
4 6
result{3} =
1 2 3
result{4} =
9 10 2 3
Since Matlab doesn't support non-rectangular double arrays, you'll want to settle on a cell array. One quick way to get the desired output is to combine arrayfun with logical indexing:
nonZeroVectors = arrayfun(#(k) A(k,A(k,:)~=0),1:size(A,1),'UniformOutput',false);
I used the ('UniformOutput',false) name-value pair for the reasons indicated in the documentation (I'll note that the pair ('uni',0) also works, but I prefer verbosity). This input produces a cell array with the entries
>> nonZerosVectors{:}
ans =
5
ans =
4 6
ans =
1 2 3
ans =
9 10 2 3
Given a vector such as a = [2 5 9] and a matrix such as
8 11 5
b = 2 6 1
4 9 3
What's the best way to find which column of b contains each element of a? In this example I'd want an output like [1 3 2] because 2 is in the first column, 5 is in the third column, and 9 is in the second column. For my purposes it's safe to assume that a number can only appear in one column.
One approach -
[colID,~] = find(squeeze(any(bsxfun(#eq,b,permute(a,[1 3 2])),1)))
Or if you would like to avoid squeeze and any -
[~,colID,~] = ind2sub([size(b) numel(a)],find(bsxfun(#eq,b(:),a)))
Another way would be to use ismember:
A = [2 5 9];
B = [8 11 5; 2 6 1; 4 9 3];
[~, ind] = ismember(A,B);
[~, col] = ind2sub(size(B), ind)
col =
1 3 2
Another approach:
[~, index] = ismember(a, b);
[row, col] = ind2sub(size(b, 1), index);
I got a 4-by-n matrix, like
A =
1 5 9
3 0 6
2 3 10
7 8 4
What I want to do with A is getting each half column of A as
Line1Point1 = [1 3]
Line1Point2 = [2 7]
Line2Point1 = [5 0]
Line2Point2 = [3 8]
Line3Point1 = [9 6]
Line3Point2 = [10 4]
How could I do that? I’m pretty new to matlab coding.. Any help is really appreciated..
Cheers
Use reshape function, for example:
>> A = [1 5 9;
3 0 6;
2 3 10;
7 8 4];
>> reshape(A,2,6)
ans =
1 2 5 3 9 10
3 7 0 8 6 4
Storing such information as many variables is generally a bad idea
Some options for storing and accessing are
Cell array
Line=mat2cell(A,[2,2],ones(1,size(A,2))).'
access with
Line{2,1}
ans =
5
0
Indexing
as other answers
Anonymous Function
Line=#(l,p)A(2*p-1:2*p,l)
access with
Line(2,1)
ans =
5
0
Structure
Not really a useful solution, more for interests sake
for ii=1:size(A,2);for jj=1:2;Line(ii).Point(jj).Value=A(2*jj-1:2*jj,ii);end;end
access with
Line(2).Point(1).Value
ans =
5
0
A(1:2,1) will give you first half of the first column.
A(3:4,1) will give you second half of the first column.
A(1:2,2) will give you first half of the second column.
A(3:4,2) will give you second half of the second column.
A(1:2,3) will give you first half of the third column.
A(3:4,3) will give you second half of the third column.
You can create the variables with the eval function, which executes the input string. Using eval is commonly regarded as bad practice since it is horrible to debug.
Nevertheless, here's the code:
A = [1 5 9; 3 0 6; 2 3 10; 7 8 4];
for ii = 1:length(A(1,:))
eval(['Line' num2str(ii) 'Point1 = A(1:2, ii)' ]);
eval(['Line' num2str(ii) 'Point2 = A(3:4, ii)' ]);
end
% Now all variables are created - for example: Line2Point1
A more elegant solution could be to store the vectors in a cell array. You can acces the first vectors for example by typing: c{1,1}
c = cell(length(A(1,:)),2)
for ii = 1:length(A(1,:))
c{ii,1} = A(1:2, ii);
c{ii,2} = A(3:4, ii);
end
I would suggest using 3D arrays to store and then access those values.
Code
N = size(A,1)/2;
LinePoint = permute(reshape(A,N,size(A,1)/N,[]),[1 3 2])
Here,
2nd dimension indices (columns) would represent Line IDs
3rd dimension indices would represent Point IDs.
Thus, the representative 3D array would be - LinePoint(:,LineID,PointID).
Example run
For your given A, we would have LinePoint as -
LinePoint(:,:,1) =
1 5 9
3 0 6
LinePoint(:,:,2) =
2 3 10
7 8 4
Thus,
Line1Point1 would be denoted by LinePoint(:,1,1)
Line1Point2 would be denoted by LinePoint(:,1,2)
Line2Point1 would be denoted by LinePoint(:,2,1)
Line2Point2 would be denoted by LinePoint(:,2,2)
Line3Point1 would be denoted by LinePoint(:,3,1)
Line3Point2 would be denoted by LinePoint(:,3,2)