I am trying to create two vectors
first:
[ 10 9 8 7 6 5 4 3 2 1 2 3 4 5 6 7 8 9 10 ]
second:
[ 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1 ]
I had almost no problems with the first one:
i = 1:10;
for t = 1: 2*length(i)-1
y1(t) = abs(length(x)-t)+1;
end
But there are some problems with the second...
Does anyone have any idea how I can create it using the same for loop?Thanks in advance
If you want to do it with a loop:
N = 10;
for t = 1:2*N-1
y2(t) = -abs(t-N)+N;
end
But its probably easier to use the following, first make an array 1:N, and then concatenate the array N-1:-1:1:
y2 = [1:N, N-1:-1:1]
I have for example a=[1 2 3 4 5 6 7 8 9 10]; and I have to delete each 2 following numbers from 3.
like at the end it should be a=[1 4 7 10];
How to do this without a for loop.
And also if there is a way to guarantee that at the end the resulting array will have exact number of entries, like here it should be a with 4 entries at the end.
But for example we have b=[1 2 3 4 5 6 7 8 9 ]; and if I want make sure that at the end I still have 4 entries in the rest array, so that b can't be equal to [1 4 7] because I need 4 entries for sure.
You can use indexing for this:
A = 1:10;
B = A(1:3:end)
B =
[1 4 7 10]
Or, if you really want to remove elements:
A = 1:10;
A(2:3:end) = [];
A(3:3:end) = [];
For your second question regarding length checking, it's unclear what you're asking. Would an if comparison be enough ?
if numel(A) ~= 4
% ... Handle unexpected values here
end
Best,
As you mentioned in the question and in the comments that you need 4 elements at the end and if elements are less than 4 then you want to include the last element/s of b, the following should work:-
b=[1 2 3 4 5 6 7 8 9]
b_req=b(1:3:end);
temp=length(b_req);
if temp<4 b_req(end+1:4)=b(end-3+temp:end); % for including the elements of b so that total elements are 4 at the end
elseif temp>4 b_req=b_req(1:4); % for removing the extra elements
end
b_req
Output:-
b =
1 2 3 4 5 6 7 8 9
b_req =
1 4 7 9
and
if instead b=[1 2 3 4 5 6 7 8 9 10]; then the same code gives what you require, i.e. b_req = [1 4 7 10]
This code speaks for itself:
a = 1:15; % some vector
% returns every third element after the first one:
third_elemets = a(1:3:end);
% returns the missing elements for the vector to be in size 4 from the end of a
last_elements = a(end-3+length(third_elemets):end);
% take maximum 4 elements from a
logic_ind = true(min(4,length(third_elemets)),1);
% and concatanate them with last_elements (if there are any)
a = [third_elemets(logic_ind) last_elements]
and under the assumption that whenever there are less than 4 elements you simply take the last one(s) - it should always work.
This question already has an answer here:
Multiply 2D Matrix with vector to span third dimension - MATLAB
(1 answer)
Closed 7 years ago.
Here what I would like to achieve:
I have a matrix C
C=[1 2 3; 4 5 6; 7 8 9];
And a vector a
a=[1 2];
I would like to make such an operation, that each element of the a vector is multiplied with C ( scalar multiplication ) and out comes a 3-dimensional array D:
(:,:,1) =
1 2 3
4 5 6
7 8 9
(:,:,2) =
2 4 6
8 10 12
14 16 18
It would certainly work with a loop, but, since I'll need this operation on multiple occasions, a oneliner would be a great saver.
This is a beautiful example for the use of bsxfun and reshape. While #thewaywewalks proposes first calling bsxfun and reshaping the result, I'd suggest the opposite. This makes one of the key concepts of bsxfun - the singleton dimension expansion - more clear:
out = bsxfun(#times,C,reshape(a,1,1,[]))
ans(:,:,1) =
1 2 3
4 5 6
7 8 9
ans(:,:,2) =
2 4 6
8 10 12
14 16 18
With reshape(a,1,1,[]), you make a be in the third dimension. If you now apply bsxfun, it will multiply the matrix C with each element of a.
Some reshape'ing and some bsxfun will do:
out = reshape(bsxfun(#mtimes, C(:), a(:).'), [size(C),numel(a)] )
As suggested in hbaderts answer one could also use bsxfun's capability of dimension expansion, and provide a permuted vector of factors:
out = bsxfun(#mtimes,C,permute(a,[3,1,2]))
out(:,:,1) =
1 2 3
4 5 6
7 8 9
out(:,:,2) =
2 4 6
8 10 12
14 16 18
I have another method for the benchmark compare...
IMO it's the neatest way, at least for the syntax/readability term:
out = reshape(kron(a,C),[size(C),numel(a)]);
out(:,:,1) =
1 2 3
4 5 6
7 8 9
out(:,:,2) =
2 4 6
8 10 12
14 16 18
Another possibility is to use matrix multiplication of C as a column vector times a as a row vector (this gives all element-wise products), and then reshape the result:
out = reshape(C(:)*a, size(C,1), size(C,2), numel(a));
EDIT (BENCHMARKING): Since several solutions (including mine below) have been suggested, here is some rough benchmarking to compare the different solutions, using larger arrays:
a=1:10;
N=1000; timers=zeros(N,6);
for ii=1:N; C=rand(400);
tic; out = repmat(C,[1,1,numel(a)]).*reshape(repelem(a,size(C,1),size(C,2)),[size(C),numel(a)]); timers(ii,1)=toc;
tic; out = bsxfun(#times,C,reshape(a,1,1,[])); timers(ii,2)=toc;
tic; out = reshape(C(:)*a, size(C,1), size(C,2), numel(a)); timers(ii,3)=toc;
tic; out = bsxfun(#mtimes,C,permute(a,[3,1,2])); timers(ii,4)=toc;
tic; out = reshape(bsxfun(#mtimes, C(:), a(:).'), [size(C),numel(a)] ); timers(ii,5)=toc;
tic; out = reshape(kron(a,C),[size(C),numel(a)]); timers(ii,6)=toc;
end;
mean(timers)
ans =
0.0080863 0.0032406 0.0041718 0.015166 0.0074462 0.0033051
... suggesting that #hbaderts solution is fastest, then #Adiel's, then #Luis Mendo's, then #thewaywewalk's (1), then mine, then #thewaywewalk's (2).
My solution:
Another option, using repmat and reshape (no bsxfun):
out = repmat(C,[1,1,numel(a)]).*reshape(repelem(a,size(C,1),size(C,2)),[size(C),numel(a)])
out(:,:,1) =
1 2 3
4 5 6
7 8 9
out(:,:,2) =
2 4 6
8 10 12
14 16 18
This is the element-wise multiplication of two arrays. The first is your original matrix C repeated numel(a) times in the third dimension:
repmat(C,[1,1,numel(a)])
ans(:,:,1) =
1 2 3
4 5 6
7 8 9
ans(:,:,2) =
1 2 3
4 5 6
7 8 9
The second is the same size as the first, with each slice containing the corresponding element of a:
reshape(repelem(a,size(C,1),size(C,2)),[size(C),numel(a)])
ans(:,:,1) =
1 1 1
1 1 1
1 1 1
ans(:,:,2) =
2 2 2
2 2 2
2 2 2
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 have a vector in R like this
a = c(5,7,8)
And I want to generate a vector of its elements using a vector that indicates the elements' position in a, e.g.
b = c(1,1,1,3,3,2,2,2,2)
which should result in
5 5 5 8 8 7 7 7 7
How can I accomplish this?
You can try [ with 'b' as index
a[b]
#[1] 5 5 5 8 8 7 7 7 7
b = c(a[1],a[1],a[1],a[3],a[3],a[2],a[2],a[2],a[2])
or
b = c(rep(a[1],3),rep(a[3],2),rep(a[2],4))