I have two vectors and I want the numbers to follow one each other. By this I mean:
a = [5 6 4 2 1];
b = [4 2 1 3];
Vector b can be smaller than a by one or can be the same length
I want to get
c = [5 4 6 2 4 1 2 3 1];
I tried to use reshape but gave up. So I just implemented the loop.
But is there a better way to solve this problem?
You can use sliced assignment:
% prepare c
c = zeros(1, length(a) + length(b));
% assign a
c(1:2:length(a)*2) = a;
% assign b
c((1:2:length(b)*2)+1) = b;
Note: This solution does not verify if either a or b are too short. Too long a or b will give an error though.
AFAIK reshape is only usable to change the dimensions of a single array/matrix.
Why not use simple concatenation and reordering?
>> a = [5 6 4 2 1];
>> b = [4 2 1 3];
>> c = [a b]; % initialize by concatenation
>> c([1:2:end 2:2:end]) = c % reorder by sliced re-assignment
c =
5 4 6 2 4 1 2 3 1
Related
This question already has answers here:
Octave / Matlab: Extend a vector making it repeat itself?
(3 answers)
Closed 5 years ago.
I think it should be very easy, but i donĀ“t know how to a append a vector by his own within a loop.
For example:
a = [1 2 3]
I would like to have:
b = [1 2 3 1 2 3 1 2 3]
So, there must be an empty array where i append the a vector 3 times via a loop?
The answer is to use the built-in function repmat
a = [1 2 3]
% Repeat 1x in the rows dimension, 3x in the columns dimension
b = repmat( a, 1, 3 );
% >> b = [1 2 3 1 2 3 1 2 3]
To append two vectors use the [a, b] notation.
For your example:
a = [1 2 3];
b = [];
for i=1:3
b = [b, a];
end
Edit in response to the comment about memory allocation time:
Consider pre-allocating the whole array before your loop.
a = [1 2 3];
b= zeros(1, size(a,2)*3);
s_a = size(a,2);
for i=1:3
b(((i-1)*s_a + 1):i*s_a) = a;
end
For example:
a = [1 2 3; 4 5 6; 7 8 9];
b = [2 4]; %//Indices I got
How can I set to zero every element of a not indexed in b in order to obtain:
0 2 0
4 0 0
0 0 0
I tried for loop:
for i = 1:numel(a)
if i ~= b
a(i) = 0;
end
end
but the matrix I cope with is really large and it takes ridiculously long time to finish running.
Is there any smart way to do it? Thank you.
Try this:
a = [1 2 3; 4 5 6; 7 8 9];
b = [2 4];
a(setdiff(1:length(a(:)),b)) = 0;
UPDATE
As proposed by #Daniel, for large matrices is better to use
a(setdiff(1:numel(a),b)) = 0;
An alternative to Anton's direct solution is one based on copying:
a = [1 2 3; 4 5 6; 7 8 9];
b = [2 4];
atmp = a(b);
a = zeros(size(a));
a(b) = atmp; %// copy needed elements
I guess efficiency of the two approaches boils down to allocation vs setdiff. Also, if your resulting matrix has many zeroes, you should perhaps consider using a sparse matrix.
I have a m-by-n matrix and I want to shift each row elements k no. of times (" one resultant matrix for each one shift so a total of k matrices corresponding to each row shifts ")(k can be different for different rows and 0<=k<=n) and want to index all the resultant matrices corresponding to each individual shift.
Eg: I have the matrix: [1 2 3 4; 5 6 7 8; 2 3 4 5]. Now, say, I want to shift row1 by 2 times (i.e. k=2 for row1) and row2 by 3times (i.e. k=3 for row2) and want to index all the shifted versions of matrices (It is similar to combinatorics of rows but with limited and diffeent no. of shifts to each row).
Can someone help to write up the code? (please help to write the general code but not for the example I mentioned here)
I found the following question useful to some extent, but it won't solve my problem as my problem looks like a special case of this problem:
Matlab: How to get all the possible different matrices by shifting it's rows (Update: each row has a different step)
See if this works for you -
%// Input m-by-n matrix
A = rand(2,5) %// Edit this to your data
%// Initialize shifts, k for each row. The number of elements would be m.
sr = [2 3]; %// Edit this to your data
[m,n] = size(A); %// Get size
%// Get all the shits in one go
sr_ind = arrayfun(#(x) 0:x,sr,'un',0); %//'
shifts = allcomb(sr_ind{:},'matlab')'; %//'
for k1 = 1:size(shifts,2)
%// Get shift to be used for each row for each iteration
shift1 = shifts(:,k1);
%// Get circularly shifted column indices
t2 = mod(bsxfun(#minus,1:n,shift1),n);
t2(t2==0) = n;
%// Get the linear indices and use them to index into input to get the output
ind = bsxfun(#plus,[1:m]',(t2-1)*m); %//'
all_matrices = A(ind) %// outputs
end
Please note that this code uses MATLAB file-exchange code allcomb.
If your problem in reality is not more complex than what you showed us, it can be done by a double loop. However, i don't like my solution, because you would need another nested loop for each row you want to shift. Also it generates all shift-combinations from your given k-numbers, so it has alot of overhead. But this can be a start:
% input
m = [1 2 3 4; 5 6 7 8; 2 3 4 5];
shift_times = {0:2, 0:3}; % 2 times for row 1, 3 times for row 2
% desird results
desired_matrices{1} = [4 1 2 3; 5 6 7 8; 2 3 4 5];
desired_matrices{2} = [3 4 1 2; 5 6 7 8; 2 3 4 5];
desired_matrices{3} = [1 2 3 4; 8 5 6 7; 2 3 4 5];
desired_matrices{4} = [4 1 2 3; 8 5 6 7; 2 3 4 5];
desired_matrices{5} = [3 4 1 2; 8 5 6 7; 2 3 4 5];
% info needed:
[rows, cols] = size(m);
count = 0;
% make all shift combinations
for shift1 = shift_times{1}
% shift row 1
m_shifted = m;
idx_shifted = [circshift([1:cols]',shift1)]';
m_shifted(1, :) = m_shifted(1, idx_shifted);
for shift2 = shift_times{2}
% shift row 2
idx_shifted = [circshift([1:cols]',shift2)]';
m_shifted(2, :) = m_shifted(r_s, idx_shifted);
% store them
store{shift1+1, shift2+1} = m_shifted;
end
end
% store{i+1, j+1} stores row 1 shifted by i and row 2 shifted by j
% example
all(all(store{2,1} == desired_matrices{1})) % row1: 1, row2: 0
all(all(store{2,2} == desired_matrices{4})) % row1: 1, row2: 1
all(all(store{3,2} == desired_matrices{5})) % row1: 2, row2: 1
The following codes runs in Matlab:
a = [1 2 3 4]
b = [ 1 2 3; 1 2 3; 1 2 3]
a(b)
The result of a(b) is a matrix:
[ 1 2 3; 1 2 3; 1 2 3]
Can anyone explain what happened here? Why a vector can be indexed by a matrix, how to interpret the result?
That's a very standard MATLAB operation that you're doing. When you have a vector or a matrix, you can provide another vector or matrix in order to access specific values. Accessing values in MATLAB is not just limited to single indices (i.e. A(1), A(2) and so on).
For example, what you have there is a vector of a = [1 2 3 4]. When you try to use b to access the vector, what you are essentially doing is a lookup. The output is basically the same size as b, and what you are doing is creating a matrix where there are 3 rows, and each element accesses the first, second and third element. Not only can you do this for a vector, but you can do this for a matrix as well.
Bear in mind that when you're doing this for a matrix, you access the elements in column major format. For example, supposing we had this matrix:
A = [1 2
3 4
5 6
7 8]
A(1) would be 1, A(2) would be 3, A(3) would be 5 and so on. You would start with the first column, and increasing indices will traverse down the first column. Once you hit the 5th index, it skips over to the next column. So A(5) would be 2, A(6) would be 4 and so on.
Here are some examples to further your understanding. Let's define a matrix A such that:
A = [5 1 3
7 8 0
4 6 2]
Here is some MATLAB code to strengthen your understanding for this kind of indexing:
A = [5 1 3; 7 8 0; 4 6 2]; % 3 x 3 matrix
B = [1 2 3 4];
C = A(B); % C should give [5 7 4 1]
D = [5 6 7; 1 2 3; 4 5 6];
E = A(D); % E should give [8 6 3; 5 7 4; 1 8 6]
F = [9 8; 7 6; 1 2];
G = A(F); % G should give [2 0; 3 6; 5 7]
As such, the output when you access elements this way is whatever the size of the vector or matrix that you specify as the argument.
In order to be complete, let's do this for a vector:
V = [-1 9 7 3 0 5]; % A 6 x 1 vector
B = [1 2 3 4];
C = V(B); % C should give [-1 9 7 3]
D = [1 3 5 2];
E = V(D); % E should give [-1 7 0 9]
F = [1 2; 4 5; 6 3];
G = V(F); % G should give [-1 9; 3 0; 5 7]
NB: You have to make sure that you are not providing indexes that would make the accessing out of bounds. For example if you tried to specify the index of 5 in your example, it would give you an error. Also, if you tried anything bigger than 9 in my example, it would also give you an error. There are 9 elements in that 3 x 3 matrix, so specifying a column major index of anything bigger than 9 will give you an out of bounds error.
Notice that the return value of a(b) is the same size as b.
a(b) simply takes each element of b, call it b(i,j), as an index and returns the outputs a(b(i,j)) as a matrix the same size as b. You should play around with other examples to get a more intuitive feel for this:
b = [4 4 4; 4 4 4];
a(b) % Will return [4 4 4; 4 4 4]
c = [5; 5];
a(c) % Will error as 5 is out of a's index range
I have a trouble find a matlab function/code to do following task
I have a vector C = [1 1 2 2 2 3 3 4]
I need resulting vector Y = [1 2 1 2 3 1 2 1]
You could create a function like the following:
C = [1 1 2 2 2 3 3 4]
Y = zeros(1,length(C))
helper = zeros(1,max(C)) % stores the count for each value
for i=1:length(C)
helper(C(i)) = helper(C(i))+1; %increases the count for the value in C(i)
Y(i) = helper(C(i));
end
Hope that helps
Try this out, if you want it in a one-liner, this will work...
Y = sum(cumsum(meshgrid(C)==meshgrid(C)',2).*(meshgrid(C)==meshgrid(C)').*eye(length(A)),1);
Not the prettiest, but it will work (you can always split it up to make it clearer)