So, I want to plot some points like this (sorry for my pathetic drawing):
So, simply I have some points for the corresponding numbers in x, and I want to plot them based on their values on Y-axis.
I also need to connect the mean of each column (the Y indices) with a straight line, like viz.
Edit: This means say the column with X index 5 has average of 5.6, 10 has 4.5 etc. I want a curve to connect average values of each column. The blue line is connecting the averages of each column.
I wrote a code that fails with the following error:
Error using scatter (line 62)
X and Y must be vectors of the same length.
Here is the code:
x = [5,10,15,20];
scatter(4, data_tab.Bitsi);
hold on
scatter(8, data_tab.Bitsa);
scatter(12, data_tab.Bitsb);
scatter(16, data_tab.Bitsc);
scatter(20, data_tab.Bitsd);
Each of the columns for 5, 10 ... has 4 values as well.
How do I do it?
Thanks.
This is not an elegant solution but it plots what you want
a = rand(1,4);
mean_a = mean(a);
b = rand(1,4);
mean_b = mean(b);
c = rand(1,4);
mean_c = mean(c);
d = rand(1,4);
mean_d = mean(d);
e = rand(1,4);
mean_e = mean(e);
means_array = [mean_a mean_b mean_c mean_d mean_e];
x = [5,10,15,20];
scatter([4 4 4 4], a);
hold on
scatter([8 8 8 8], b);
scatter([12 12 12 12], c);
scatter([16 16 16 16], d);
scatter([20 20 20 20], e);
plot([4 8 12 16 20], means_array);
The problem with your code was that you weren´t supplying the same number of elements in the x and y vectors of the scatter function
Related
I have a 2000x2 matrix, and "for each 10x2 segment of this matrix", I need to calculate the maximum of corresponding values (second column) of repetitive values (first column) in the matrix. Like if the 3rd 10x2 segment of the matrix is this:
...
[2 20;
2 30;
2 40;
7 100;
7 110;
7 120;
7 130;
7 140;
15 240;
15 260]
...
I want to get this:
...
[2 40;
7 140;
15 260]
...
And so on. I have written the following but it gives me the maximum of repetitive elements through the "whole matrix":
[uv,~,idx] = unique(A(:,1));
B = [uv accumarray(idx,A(:,2),[],#max)];
But again, I need to do this "for each separate 10x2 segments of the matrix", and then store the results in a 'whatever x 2' sized matrix! Does anyone have any ideas how I could do this?
Instead of using A(:,2) as the argument to accumarray you can use indices of values and use them to extract elements in the function handle.
A = randi(5,50,2);
val = (1:size(A,1)).';
B = accumarray( ...
[A(:,1) ceil(val/10)], val, [], ...
#(x){[ A(x(1), 1) max(A(x, 2)) ]} ...
);
result = vertcat(B{:});
I have a 9 x 682 matrix (A). Every 36 columns correspond to a new variable (17 variable in total). For each variable (36 columns), I want to calculate the mean of every 6th column (i.e. mean of columns 1, 7, 13, 19, 31 and so on for each block of 36 columns.
I am stuck with the use of several For loops.
A_averaged = zeros(9,102);
for i = 1:36:length(A)
for j = i:i+35
for k = j:6:j+1
A_averaged(:,k) = mean(A(:,k), 2);
end
end
end
Any help is much appreciated.
To vectorize this, I would reshape your data in a smart way, select the columns you want, and then compute the mean.
% Reshape data to 3D with dimensions: 9 x 36 x (nGroups)
B = reshape(A, size(A, 1), 36, []);
% Now grab the columns of each chunk you want
C = B(:, 1:6:end, :);
% Now compute the mean along the first dimension and squeeze the result
result = squeeze(mean(C, 1));
You can do this in one line with the following:
result = squeeze(mean(reshape(A(:, 1:6:end), size(A, 1), 6, []), 1))
If you instead want the mean of all rows and columns, you can reshape your data into 45 x nGroups and compute the mean along the first dimension
result = mean(reshape(C, [], size(C, 3)), 1);
As a side note, your initial dimensions of 9 x 682 are not actually divisible by 36 columns. Did you mean 9 x 612?
I want to select a random subset of a vector, much like datasample(data,k), but I want them in order.
I have an ODE which has [t,y] as output and it's the y that I want a subset of. I cannot just do a sort because y is not linear and so I somehow have to sort it with respect to t.
Any ideas how I can to this?
If I understand correctly, you want to sample the elements maintaining their original order. You can do it this way:
randomly sample the indices rather than the values;
sort the sampled indices;
use them to access the selected values;
that is:
result = data(sort(randsample(numel(data), k)));
The above uses the randsample function from the Statistics Toolbox. Alternatively, in recent Matlab versions you can use the two-input form of randperm:
result = data(sort(randperm(numel(data), k)));
For example, given
data = [61 52 43 34 25 16];
k = 4;
a possible result is
result =
61 43 34 25
This can be solved using a combination of randperm and intersect:
function q40673112
% Create a vector:
v = round(sin(0:0.6:6),3); disp(['v = ' mat2str(v)]);
% Set the size of sample we want:
N = 5;
% Create the random indices:
inds = intersect(1:numel(v), randperm(numel(v),N)); disp(['inds = ' mat2str(inds)]);
% Sample from the vector:
v_samp = v(inds); disp(['v_samp = ' mat2str(v_samp)]);
Example output:
% 1 2 3 4 5 6 7 8 9 10 11
v = [0 0.565 0.932 0.974 0.675 0.141 -0.443 -0.872 -0.996 -0.773 -0.279]
inds = [4 6 9 10 11]
v_samp = [0.974 0.141 -0.996 -0.773 -0.279]
I have data recorded from a device (250-Hz sampling device, ~100K measurements total so about 400 seconds worth). I want to create (overlapping) windows of 512 (~2 seconds) or 1024 (~4 seconds) measurements each, perhaps in ~0.5 second intervals. I'm using Matlab.
Is there a particular way to accomplish this goal? I imagine I want to use a filter to accomplish this goal? Would it change if I wanted to apply, say, a Hann window as well?
Thanks for the help!
Let your data be a row vector. You can use blockproc if you:
choose the "blockSize" argument as [1 S], where S is window step;
use the 'BorderSize' option to set borders [0 B]. Window length will be S+2*B;
set the 'TrimBorder' property to false;
define an appropriate function to apply to each window data.
For example, say you a length-5 window with step 3, and you want the sum of all elements in each window:
>> x = 1:12;
>> y = blockproc(x, [1 3], #(t) sum(t.data), 'Bordersize', [0 1], 'TrimBorder', false)
y =
10 25 40 42
where
%// 0+1+2+3+4 = 10
%// 3+4+5+6+7 = 25
%// 6+7+8+9+10 = 40
%// 9+10+11+12+0 = 42
Note the zero padding at the initial and final windows. To avoid that, include an adequate amount of initial zeros in the data, choose data size appropriately, and discard initial and final output values:
>> x = 1:14;
>> y = blockproc([0 0 x], [1 3], #(t) sum(t.data), 'Bordersize', [0 1], 'TrimBorder', false)
y =
3 15 30 45 60 27
where
%// 1+2+3+4+5 = 15
%// 4+5+6+7+8 = 30
%// 7+8+9+10+11 = 45
%// 10+11+12+13+14 = 60
I'm a total beginner to matlab and I'm currently writing a script for extracting data from a thermographic video.
Firstly the video is cut in separate frames. The first frame is opened as a sample picture to define the coordinates of sampling points. The goal is then to select the rgb values of those defined coordinates from a set of frames and save them into a matrix.
Now I have a problem separating the matrix to n smaller matrices.
e.g I'm defining the number of points to be selected to n=2 , with a picture count of 31. Now it returns a matrix stating the rgb codes for 31 pictures, each at 2 points, in a 62x3 double matrix...
Now I want to extract the 1st, 3rd, 5th....etc... row to a new matrix...this should be done in a loop, according to the number of n points...e.g 5 points on each picture equals 5 matrices, containing values of 31 pictures....
this is an extract of my code to analyse the pictures, it returns the matrix 'values'
files = dir('*.jpg');
num_files = numel(files);
images = cell(1, num_files);
cal=imread(files(1).name);
n = input('number of selection points?: ');
imshow(cal);
[x,y] = ginput(n);
eval(get(1,'CloseRequestFcn'))
%# x = input('x-value?: '); manual x selection
%# y = input('y-value?: '); manual y selection
for k = 1:num_files
images{k} = imread(files(k).name);
end
matrix=cell2mat(images);
count=(0:size(matrix,1):size(matrix,1)*num_files);
for k = 1:num_files
a(k)= mat2cell(impixel(matrix,x+count(k),y));
end
values = cat(1,a{:})
Easy fix
Do you mean that if you have:
n = 2;
k = 2; % for example
matrix = [1 2 3;
4 5 6;
7 8 9;
8 7 6];
you want it to become
b{1} = [1 2 3;
7 8 9];
b{2} = [4 5 6;
8 7 6];
This can be easily done with:
for ii = 1:n
b{ii} = matrix(1:n:end,:);
end
Better fix
Of course it's also possible to just reshape your data matrix and use that instead of the smaller matrices: (continuing with my sample data ^^)
>> d=reshape(matrix',3,2,[]);
>> squeeze(d(:,1,:))
ans =
1 7
2 8
3 9
>> squeeze(d(:,2,:))
ans =
4 8
5 7
6 6
Good practice
Or, my preferred choice: save the data immediately in an easy to access way. Here I think it will be an matrix of size: [num_files x num_points x 3]
If you want all the first points:
rgb_data(:,1,:)
only the red channel of those points:
rgb_data(:,1,1)
and so on.
I think this is possible with this:
rgb_data = zeros(num_files, num_points, 3);
for kk = 1:num_files
rgb_data(kk,:,:) = impixel(images{kk},x+count(k),y);
end
But I don't understand the complete meaning of your code (eg: why matrix=cell2mat(images) ??? and then of course:
count=(0:size(matrix,1):size(matrix,1)*num_files);
is just count=0:num_files;
so I'm not sure what would come out of impixel(matrix,x+count(k),y) and I used images{k} :)