Having the values of time sequence, I would like to reshape it into a nx4 matrix [X y], for the purpose of using these values as input and output values for machine learning algorithm.
X(i) is a 1x3 input vector and y is output scalar value.
The algorithm takes as an input every 2nd sequence value (3 values) in order to predict the 4th value.
To give a practical example, let's say we have a sequence
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
The [X y] matrix should be the following:
[1 3 5 7; 2 4 6 8; 9 11 13 15; 10 12 14 16]
To get every second row I wrote the following code:
vec1 = timeSeries(1:2:end);
XyVec1 = reshape(vec1,4,[])'
similarly it could be written to get even numbers:
vec2 = timeSeries(2:2:end);
XyVec2 = reshape(vec2,5,[])'
The thing that I don't know how to do is to interleave matrix vec1 and vec2 rows to get
[vec(1,:); vec2(1,:);vec1(2,:), vec2(2,:)...]
Does anyone know how to interleave the rows of two (or more) matrices?
Try
result = zeros(size(vec1,1)+size(vec2,1),size(vec1,2));
result(1:2:end,:) = vec1;
result(2:2:end,:) = vec2;
Reuse matlab indexing facilities ot insert elements in correct rows
Sample octave mock-up: http://ideone.com/RVgmYA
There is this one-liner option
result = kron(vec1, [1;0]) + kron(vec2, [0;1]);
However, #Joel Falcou is faster. Having set the input vectors as
vec1 = rand(1000,1000);
vec2 = -rand(1000,1000);
it gives
Elapsed time is 0.007620 seconds. (indexing)
Elapsed time is 0.054607 seconds. (kron)
Good luck :) figuring out what's going on with those reshape(), permutes():
a = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16];
reshape(permute(reshape(a,2,4,[]),[2,1,3]),4,[])'
the result
ans =
1 3 5 7
2 4 6 8
9 11 13 15
10 12 14 16
To interleave the vectors as mentioned in the end of your question you can use
reshape([vec1, vec2]', 4, [])'
for
vec1 =
1 3 5 7
9 11 13 15
vec2 =
2 4 6 8
10 12 14 16
it returns
>> reshape([vec1, vec2]', 4, [])'
ans =
1 3 5 7
2 4 6 8
9 11 13 15
10 12 14 16
Related
I am totally new to Matlab and have a simple question (not that simple for me):
I have a matrix x:
x = 1 2 3
4 5 6
7 8 9
10 11 12
and a Vector y:
y = 1 2 3
Now I would like to multiply the numbers 1 to 4 by the first element of the Vector, the numbers 5 to 8 by the second element and 9 to 12 by the last element.
CanĀ“t find a solution. Any help is highly appreciated!
Thanks Paul
If you modify your input x to set up all "groups" as columns of a new input, let's say xx, e.g. by transposing and reshaping x accordingly, you can use (element-wise) multiplication. MATLAB's implicit expansion allows such (element-wise) matrix operations. (Before MATLAB R2016b, one would need bsxfun for that.)
That would be my solution:
% Inputs
x = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
y = [1 2 3]
% Transpose and reshape x to set up all "groups" as new columns
xx = reshape(x.', 4, 3)
% (Element-wise) Multiplication using implicit expansion
z = xx .* y
Output:
x =
1 2 3
4 5 6
7 8 9
10 11 12
y =
1 2 3
xx =
1 5 9
2 6 10
3 7 11
4 8 12
z =
1 10 27
2 12 30
3 14 33
4 16 36
Hope that helps!
Consider a row vector A and row vector B. For example:
A = [1 2 3 7 8 10 12];
B = [1 1 2 2 2 3 5 6 6 7 7 7 8 8 10 10 10 11 12 12 12 13 15 16 18 19];
A has previously been checked to be a subset of B. By subset, I specifically mean that all elements in A can be found in B. I know that elements in A will not ever repeat. However, the elements in B are free to repeat as many or as few times as they like. I checked this condition using:
is_subset = all(ismember(A,B));
With all that out of the way, I need to know the indices of the elements of A within B including the times when these elements repeat within B. For the example A and B above, the output would be:
C = [1 2 3 4 5 6 10 11 12 13 14 15 16 17 19 20 21];
Use ismember to find the relevant logical indices. Then convert them to linear indices using find.
C = find(ismember(B,A));
You can find the difference of each element of A with B, and get the indices you want. Something like below:
A = [1 2 3 7 8 10 12];
B = [1 1 2 2 2 3 5 6 6 7 7 7 8 8 10 10 10 11 12 12 12 13 15 16 18 19];
C = [1 2 3 4 5 6 10 11 12 13 14 15 16 17 19 20 21];
tol = 10^-3 ;
N = length(A) ;
iwant = cell(N,1) ;
for i = 1:N
idx = abs(A(i)-B)<=tol ;
iwant{i} = find(idx) ;
end
iwant = [iwant{:}] ;
Let's say I have a vector:
A=[1 2 3 6 7 8 11 12 13]
and I'm trying to achieve final output like:
[1 6 11 2 7 12 3 8 13]
Where the vector is rearranged to front every nth column, in this case, 3rd. Using indexing will work, but it requires a loop, which I'm trying to avoid. Any idea how to do it in a vectorized way? Thanks!
nth=3;
for i=1:nth:size(A,2)
A_(:,nth)= A(:,i:nth:end)
end
The suggestion that #jodag posted in the comments works totally fine. Alternatively, this should also do the job... but the constraint is the same, A must be divisible by nth:
nth = 3;
A = [1 2 3 6 7 8 11 12 13];
A_len = numel(A);
A_div = floor(A_len / nth);
seq = repmat(1:nth:A_len,1,A_div);
inc = sort(repmat(0:nth-1,1,A_div));
A = A(seq + inc)
Output:
A =
1 6 11 2 7 12 3 8 13
As I am trying to multiply a m x n Matrix with a p-dimensional vector, I am stumbling across some difficulties.
Trying to avoid for loops, here is what I am looking to achieve
enter code here
M = [1 2 3; p = [1;2;3]
4 5 6;
7 8 9]
I want to obtain a 3x3x3 matrix, where the slices in third dimension are simply the entries of M multiplied by the respective entry in p.
Help is much appreciated
You can use bsxfun with permute for a vectorized (no-loop) approach like so -
out = bsxfun(#times,M,permute(p(:),[3 2 1]))
You would end up with -
out(:,:,1) =
1 2 3
4 5 6
7 8 9
out(:,:,2) =
2 4 6
8 10 12
14 16 18
out(:,:,3) =
3 6 9
12 15 18
21 24 27
With matrix-multiplication -
out = permute(reshape(reshape(M.',[],1)*p(:).',[size(M) numel(p)]),[2 1 3])
I've a vector that I would like to split into overlapping subvectors of size cs in shifts of sh. Imagine the input vector is:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
given a chunksize of 4 (cs=4) and shift of 2 (sh=2), the result should look like:
[1 2 3 4]
[3 4 5 6]
[5 6 7 8]
[7 8 9 10]
[9 10 11 12]
note that the input vector is not necessarily divisible by the chunksize and therefore some subvectors are discarded. Is there any fast way to compute that, without the need of using e.g. a for loop?
In a related post I found how to do that but when considering non-overlapping subvectors.
You can use the function bsxfun in the following manner:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
A = v(bsxfun(#plus,(1:cs),(0:sh:length(v)-cs)'));
Here is how it works. bsxfun applies some basic functions on 2 arrays and performs some repmat-like if the sizes of inputs do not fit. In this case, I generate the indexes of the first chunk, and add the offset of each chunck. As one input is a row-vector and the other is a column-vector, the result is a matrix. Finally, when indexing a vector with a matrix, the result is a matrix, that is precisely what you expect.
And it is a one-liner, (almost) always fun :).
Do you have the signal processing toolbox? Then the command is buffer. First look at the bare output:
buffer(v, 4, 2)
ans =
0 1 3 5 7 9 11
0 2 4 6 8 10 12
1 3 5 7 9 11 13
2 4 6 8 10 12 0
That's clearly the right idea, with only a little tuning necessary to give you exactly the output you want:
[y z] = buffer(v, 4, 2, 'nodelay');
y.'
ans =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
That said, consider leaving the vectors columnwise, as that better matches most use cases. For example, the mean of each window is just mean of the matrix, as columnwise is the default.
I suppose the simplest way is actually with a loop.
A vectorizes solution can be faster, but if the result is properly preallocated the loop should perform decently as well.
v = 1:13
cs = 4;
sh = 2;
myMat = NaN(floor((numel(v) - cs) / sh) + 1,cs);
count = 0;
for t = cs:sh:numel(v)
count = count+1;
myMat(count,:) = v(t-cs+1:t);
end
You can accomplish this with ndgrid:
>> v=1:13; cs=4; sh=2;
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1)
>> chunks = X+Y
chunks =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
The nice thing about the second syntax of the colon operator (j:i:k) is that you don't have to calculate k exactly (e.g. 1:2:6 gives [1 3 5]) if you plan to discard the extra entries, as in this problem. It automatically goes to j+m*i, where m = fix((k-j)/i);
Different test:
>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y
chunks =
1 2 3 4 5
4 5 6 7 8
7 8 9 10 11
10 11 12 13 14
And a new row will form with v=1:17. Does this handle all cases as needed?
What about this? First I generate the starting-indices based on cs and sh for slicing the single vectors out of the full-length vector, then I delete all indices for which idx+cs would exceed the vector length and then I'm slicing out the single sub-vectors via arrayfun and afterwards converting them into a matrix:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
idx = 1:(cs-sh):length(v);
idx = idx(idx+cs-1 <= length(v))
A = arrayfun(#(i) v(i:(i+cs-1)), idx, 'UniformOutput', false);
cell2mat(A')
E.g. for cs=5; sh=3; this would give:
idx =
1 3 5 7
ans =
1 2 3 4 5
3 4 5 6 7
5 6 7 8 9
7 8 9 10 11
Depending on where the values cs; sh come from, you'd probably want to introduce a simple error-check so that cs > 0; as well as sh < cs. sh < 0 would be possible theoretically if you'd want to leave some values out in between.
EDIT: Fixed a very small bug, should be running for different combinations of sh and cs now.