I'm having trouble understanding the datatypes in matlab. Why does this produce two different datatypes?
data = [25 8 15 5 6 10 10 3 1 20 7]
v = [1:8]
The first one produces a 1x11 double somehow and the second one I believe produces a vector right? How is the first one able to work with findpeaks when the documentation says it wants a vector?
I was trying to do this.
http://www.cyclismo.org/tutorial/matlab/vector.html
Typing
data = [25 8 15 5 6 10 10 3 1 20 7]
v = [1:8]
whos
returns
data =
25 8 15 5 6 10 10 3 1 20 7
v =
1 2 3 4 5 6 7 8
Name Size Bytes Class Attributes
data 1x11 88 double
v 1x8 64 double
so they are both the same, and I'd call them 1x11 vectors of doubles.
Related
This is a snippet from a program I am trying to understand. I have changed the variable names for easier understanding. I haven't done much coding in MatLab so I can't really understand what's happening. When I kept a=magic(4) and got the output from this code I thought it was sorting or something but it doesn't seem so with the other input
a = [14 41 4 16;7 12 45 0;12 12 45 17; 3 2 1 15]
b=a(:)
c=zeros(4,4)
a is a 4x4 matrix,
b is a column vector of a,
c is a 4X4 matrix of zeros.`
for kk = 1:length(b)
c(a==b(kk)) = kk;
end
c =
1 5 9 13
2 7 11 14
7 7 11 15
4 8 12 16
if I try a=magic(4), where
a =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
then
c =
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
The answer in the comments is correct - perhaps it serves a function within the program, however out of context the code does seem pretty much pointless.
This is essentially what is happening. Suppose you have a matrix A
A = [3 4;
5 6]
Then B will look like this:
B = [3 4 5 6]
C is then created by comparing the kkth element of A to the kkth element of B. If the two are equal, then the kkth element of C will be kk.
Thus, in the example above, C will look like this:
C = [1 2;
3 4]
If, as you have found out, there are multiple entries of the same number in your original matrix A, then the final matrix C will only have the index of the last unique occurence of that number. So, if
A = [3 3;
5 6]
B = [3 3 5 6]
C = [2 2;
3 4]
The reason your first C has 7 three times is because the last position of 12 is at position 7. The reason your second C is different from your first C is because the A that it was made from is totally unique.
If I have this matrix:
A:
X Y Z
1 1 2
0 3 4
0 5 6
2 7 8
7 9 10
8 11 12
3 13 14
12 14 16
15 17 18
How could I create new matrix B, C, D and E which contains:
B:
0 3 4
0 5 6
C:
X Y Z
1 1 2
2 7 8
3 13 14
D:
7 9 10
8 11 12
E:
12 14 16
15 17 18
The idea is to construct a loop asking if 0<A<1 else 1<A<5 else 6<A<10 else 11<A<15. and create new matrix from that condition. Any idea about how to store the results of the loop?
I suggest you an approach that uses the discretize function in order to group the matrix rows into different categories based on their range. Here is the full implementation:
A = [
1 1 2;
0 3 4;
0 5 6;
2 7 8;
7 9 10;
8 11 12;
3 13 14;
12 14 16;
15 17 18
];
A_range = [0 1 5 10 15];
bin_idx = discretize(A(:,1),A_range);
A_split = arrayfun(#(bin) A(bin_idx == bin,:),1:(numel(A_range) - 1),'UniformOutput',false);
celldisp(A_split);
Since you want to consider 5 different ranges based on the first column values, the arguments passed to discretize must be the first matrix column and a vector containing the group limits (first number inclusive left, second number exclusive right, second number inclusive left, third number exclusive right, and so on...). Since your ranges are a little bit messed up, feel free to adjust them to respect the correct output. The latter is returned in the form of a cell array of double matrices in which every element contains the rows belonging to a distinct group:
A_split{1} =
0 3 4
0 5 6
A_split{2} =
1 1 2
2 7 8
3 13 14
A_split{3} =
7 9 10
8 11 12
A_split{4} =
12 14 16
15 17 18
Instead of using a loop, use logical indexing to achieve what you want. Use the first column of A and check for the ranges that you want to look for, then use this to subset into the final matrix A to get what you want.
For example, to create the matrix C, find all locations in the first column of A that are between 1 and 5, then subset the matrix along the rows using these locations:
m = A(:,1) >= 1 & A(:,1) <= 5;
C = A(m,:);
You can repeat this in a similar way for the rest of the matrices you want to create.
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.
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
How can I iterate over matrix and change values under condition.. for e.g:
I have matrix m with size 100x100 and Im doing:
m(m<10)=func(elemnt);
element should be the current element at iteration.. How do I access the current element??
Try simply
m(m<10)=func(m(m<10));
example:
m=[[1 2 3];[5 6 7];[8 9 10]]
m =
1 2 3
5 6 7
8 9 10
m(mod(m,3)==2) = m(mod(m,3)==2) * 5
m =
1 10 3
25 6 7
40 9 10
The only constraint is that your custom function can handle vectors.