I have a matrix like this:
A = 1 2 3
4 5 6
7 8 9
My question is how I want to make my matrix to be like this:
A11 = 1
A12 = 2
A13 = 3
A21 = 4
A22 = 5
A23 = 6
A31 = 7
A32 = 8
A33 = 9
Because i have to multiply A21 with A22 which is 4x5=20.
Your question is not clear to me.
To create the matrix, use ',' (or nothing) to delimit columns, ';' to delimit rows.
A = [1 2 3 ; 4 5 6 ; 7 8 9];
To access the matrix, you can use a 1-dimensional index as well as a 2-dimensional index.
E.g. A21 is A(2, 1) as well as A(0*3+2).
If you actually need variables such as 'A11', 'A12' etc. you could do as follows:
A = [1 2 3; 4 5 6; 7 8 9];
for i = 1:size(A,1)
for j = 1:size(A,2)
eval(sprintf('A%d%d = %f;',i,j,A(i,j)));
end
end
A21 * A22
# will result in 20
Maybe not the best way, but it will create the variables for you.
Related
Consider two Matlab vectors A=[1 2 3 4 5] B=[6 7 8 9 10];
I would like your advise to write a Matlab matrix C of size 32x5 where each row has :
as first element A(1) or B(1)
as second element A(2) or B(2)
as third element A(3) or B(3)
as fourth element A(4) or B(4)
as fifth element A(5) or B(5)
C should not contain equal rows. 32 comes from 2^5, where 5 is the length of A and B.
C=[1 2 3 4 5; %all elements from A (1 row)
6 2 3 4 5; %one element from B (5 rows)
1 7 3 4 5;
1 2 8 4 5;
1 2 3 9 5;
1 2 3 4 10;
6 7 3 4 5; %two elements from B (10 rows)
... ;
6 7 8 4 5; %three elements from B (10 rows)
... ;
6 7 8 9 5; %four elements from B (5 rows)]
... ;
6 7 8 9 10; %all elements from B (1 row)]
I could write down C manually, but I would like to know if there is a faster way to build it.
Similar approach as my answer to your previous question:
A = [1 2 3 4 5];
B = [6 7 8 9 10];
N = numel(A);
t = dec2bin(0:2^N-1)-'0';
[~, ind_sort] = sortrows([sum(t,2) -t]);
t = t(ind_sort, :);
AB = [A B];
ind_AB = t*N + (1:N); % or bsxfun(#plus, t*N, 1:N) in old Matlab versions
result = AB(ind_AB);
How can I remove elements in a matrix, that aren't all in a straight line, without going through a row at a time in a for loop?
Example:
[1 7 3 4;
1 4 4 6;
2 7 8 9]
Given a vector (e.g. [2,4,3]) How could I remove the elements in each row (where each number in the vector corresponds to the column number) without going through each row at a time and removing each element?
The example output would be:
[1 3 4;
1 4 4;
2 7 9]
It can be done using linear indexing at follows. Note that it's better to work down columns (because of Matlab's column-major order), which implies transposing at the beginning and at the end:
A = [ 1 7 3 4
1 4 4 6
2 7 8 9 ];
v = [2 4 3]; %// the number of elements of v must equal the number of rows of A
B = A.'; %'// transpose to work down columns
[m, n] = size(B);
ind = v + (0:n-1)*m; %// linear index of elements to be removed
B(ind) = []; %// remove those elements. Returns a vector
B = reshape(B, m-1, []).'; %'// reshape that vector into a matrix, and transpose back
Here's one approach using bsxfun and permute to solve for a 3D array case, assuming you want to remove indexed elements per row across all 3D slices -
%// Inputs
A = randi(9,3,4,3)
idx = [2 4 3]
%// Get size of input array, A
[M,N,P] = size(A)
%// Permute A to bring the columns as the first dimension
Ap = permute(A,[2 1 3])
%// Per 3D slice offset linear indices
offset = bsxfun(#plus,[0:M-1]'*N,[0:P-1]*M*N) %//'
%// Get 3D array linear indices and remove those from permuted array
Ap(bsxfun(#plus,idx(:),offset)) = []
%// Permute back to get the desired output
out = permute(reshape(Ap,3,3,3),[2 1 3])
Sample run -
>> A
A(:,:,1) =
4 4 1 4
2 9 7 5
5 9 3 9
A(:,:,2) =
4 7 7 2
9 6 6 9
3 5 2 2
A(:,:,3) =
1 7 5 8
6 2 9 6
8 4 2 4
>> out
out(:,:,1) =
4 1 4
2 9 7
5 9 9
out(:,:,2) =
4 7 2
9 6 6
3 5 2
out(:,:,3) =
1 5 8
6 2 9
8 4 4
I have two vectors a and b as an example:
a = [1 2 3 4];
b = [5 6 7 8];
I want to create strings from the indices of a and b:
c1 = a(1):b(1) = [1 2 3 4 5];
c2 = a(2):b(2) = [2 3 4 5 6];
c3 = a(3):b(3) = [3 4 5 6 7];
c4 = a(4):b(4) = [4 5 6 7 8];
Then I want to concatenate the obtained strings:
C = cat(2, c1, c2, c3, c4) = [1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8];
I would like a general solution to help me automatize this algorithm.
Solution
This should do the trick without using a loop:
>> a = [1 3 4 5];
>> b = [5 6 7 8];
>> resultstr = num2str(cell2mat(arrayfun(#(x,y) x:y,a,b,'UniformOutput',false)))
resultstr =
1 2 3 4 5 3 4 5 6 4 5 6 7 5 6 7 8
Performance
I tried to do a quick comparison between this method, Luis Mendo's method and the for loop (see e.g. A. Visser's answer). I created two arrays with pseudo-random numbers from 1 to 50 and 501 to 1000 and timed the calculation for array sizes from 1 to 300, disregarding the string conversion.
Luis Mendo's anwer is the clear winner, in terms of time complexity arrayfun seems to be on par with bsxfun. The for loop fares much worse, except for very small array sizes, but I'm not sure the timing can be trusted there.
The code can be found here. I'd be very happy to get some feedback, I'm a bit unsure about those measurements.
This can be done without loops (be they for, arrayfun or cellfun) using bsxfun's masking capability. This works also if the "strings" have different lengths, as in the following example.
a = [1 2 3];
b = [3 5 6];
m = (0:max(b-a)).'; %'
C = bsxfun(#plus, a, m);
mask = bsxfun(#le, m, b-a);
C = C(mask).';
The result in this example is:
C =
1 2 3 2 3 4 5 3 4 5 6
Try something like:
A = [1:5; 5:8];, C = [];
for i = A, C = [C i(1):i(2)]; end
Cstr = num2str(C);
I would do this:
a = [1 3 4 5]; b = [5 6 7 8];
c =[];
for i =1:length(a)
c = [c [a(i):b(i)]];
end
num2str(c)
First of all, don't assign variables as C1, C2, C3 etc, use cells for that.
I'd use a for-loop for this, though there probably is a better alternative.
a = [1 3 4 5]; b = [5 6 7 8];
C = [];
for ii = 1:length(a)
tmp = a(ii):b(ii);
C = [C tmp];
end
This way tmp stores your separate arrays, then the following line adds it to the pre-existing array C.
Just for fun:
a = [1 2 3 4]; b = [5 6 7 8];
A=fliplr(gallery('circul',fliplr([a,b])));
B=A(1:numel(a)+1,1:numel(a));
C=num2str(B(:).')
I have a matrix
q = [1 2 3 4 5 6;
7 8 9 10 11 12];
and I want to create an array d such that
d(:,:,1) = 1 2
7 8
d(:,:,2) = 3 4
9 10
d(:,:,3) = 5 6
11 12
I know how to do that using loops but i prefer not to use loops.
With reshape
out = reshape(q,size(q,1),2,[])
I want to make a function like this
>> matdup([1 2],3,4) %or any other input that user wish to enter
ans=
1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
I am stuck in my code. My logic:
m = matdup(input,row,col)
for i = 1:row
for j = 1:col
m(i, j)= input;
This is producing this:
>> matdup(1,2,2)
ans=
1 1
1 1
But failed at this:
>> matdup([1 2],3,4)
error at console:
Subscripted assignment dimension mismatch.
Error in ==> matdup at 6
m(i, j)= input
Any idea?
Method 1: Are you allowed to use ones? Try this -
A = [1 2]
rowIdx = [1 : size(A,1)]';
colIdx = [1 : size(A,2)]';
out = A(rowIdx(:, ones(3,1)), colIdx(:, ones(4,1)))
Output
out =
1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
Method 2: Are you allowed to use bsxfun and permute? Try this for the same result -
A = [1 2]
row_mapped = bsxfun(#plus,A,zeros(3,1))
out = reshape(bsxfun(#plus,row_mapped,permute(zeros(4,1),[3 2 1])),[3 8])
Matlab has a funcion called repmat that does the same.
If you want to create a similar function, you could do something like this:
function B = matdup(A, M, N)
[nr, nc] = size(A);
B = zeros([nr nc] .* [M N]);
for r = 1:M
for c = 1:N
rr = (r - 1) * nr + 1;
cc = (c - 1) * nc + 1;
B(rr:rr + nr - 1, cc:cc + nc - 1) = A;
end
end
end
Note this function is restricted to 2D matrices.
Try kron:
matdup = #(x,m,n) kron(ones(m,n),x)
Demonstration:
>> A = [5 6 7];
>> out = matdup(A,3,2)
out =
5 6 7 5 6 7
5 6 7 5 6 7
5 6 7 5 6 7
Note that you can switch the inputs to kron to effectively replicate elements rather than the whole matrix:
repel = #(x,m,n) kron(x,ones(m,n));
Demonstration:
>> A = [5 6 7];
>> out = repel(A,3,2)
out =
5 5 6 6 7 7
5 5 6 6 7 7
5 5 6 6 7 7
The replication can be done easily using mod:
function R = matdup(A, M, N)
[m n]= size(A);
R = A(mod(0:m*M-1,m)+1, mod(0:n*N-1,n)+1)