I am analyzing the efficiency of multiple circuits using matlab. The output is a maximum working distance and the power of the circuit analyzed. The output of this vectors is the following:
>> display(distance)
distance =
8 21 21 4 3 8 3 8 2 6 10 7 6 8 12 11 6 8
>>display(power)
power =
Columns 1 through 13
3.2047 3.5666 3.7578 1.8184 3.0810 3.7973 2.8699 3.3953 2.5971 3.1933 3.8191 3.7992 3.4802
Columns 14 through 18
4.1104 4.0836 3.2191 3.9155 0.2394
As you can see I have the circuit 1 that has a power of 3.2047 and a maximum distance of 8m. I have the circuit 6 that has the same maximum distance with a 3.7973 power. I want to rearrange the distance vector in order to it to be crescent (starting with 2 and ending with 21 for instance) and be able to rearrange the power accordingly. Below you have the display that I would like to see doing this to clarify this question.
>> display(distanceReorganized)
distanceReorganized =
2 3 3 4 6 6 6 7 8 8 8 8 8 10 11 12 21 21
>>display(powerReorganized)
powerReorganized =
Columns 1 through 13
2.5971 2.8699 3.0810 1.8184 3.1933 3.4802 3.9155 3.7992 0.2394 3.2047 3.3953 3.7973 4.1104
Columns 14 through 18
3.8191 3.2191 4.0836 3.5666 3.7578
Use the second output argument from sort.
[~,I] = sort(distance, 'ascend');
distanceReorganized = distance(I);
powerReorganized = power(I);
Edit: Based on your comment, sortrows should do what you are looking for:
circuitData = table(distance', power', 'VariableNames', {'Distance', 'Power'});
sortrows(circuitData,{'Distance','Power'})
You can then reassign the columns of the table to new vector variables should you wish to.
Here is the documentation for sortrows.
Related
Can I fixed number of rows randomly from the dataset?
example
A=[1 2 3 4;
5 6 7 8;
9 10 11 12;
13 14 15 16;
17 18 19 20];
I want to random select training dataset 3 rows and random select testing dataset 2 rows.
training_dataset= [1 2 3 4;
13 14 15 16;
5 6 7 8;];
and
testing_dataset= [ 9 10 11 12;
17 18 19 20];
I found only the random number from the array.
Thank you so much
This solution uses the randperm and setdiff commands.
indTrainRow = randperm(size(A,1),3)
indTestRow = setdiff(1:size(A,1),indTrainRow)
training_dataset = A(indTrainRow,:);
testing_dataset = A(indTestRow,:);
You can also use randsample but this requires the Statistics toolbox.
indTrainRow = randsample(1:size(A,1),3,'false')
After posting this I found some related posts. My mistake for not finding these before answering.
Related Posts:
Random selection of matrix columns
How can I divide/split up a matrix by rows between two other matrices?
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'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.
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
I have a vector called time, which contains time values. I'd like obtain a vector of indexes of time in which the value is between threshold x and threshold y.
This is undoubltedly trivial to do, but I'm struggling with Matlab syntax a bit, here. Any help would be greatly appreciated.
Blz
time=5:20
idx = find(time > 10 & time < 15) % indices
values=time(time(:)>10 & time(:)<15) % values
which give
time =
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
idx =
7 8 9 10
values =
11 12 13 14