how to create a histogram in matlab with required number of cells? - matlab

I am new in matlab and I am making a gremetric simulation with k = m2 and p = 1/5.
I have to generate 1000 random numbers and I must show them in a histogram with 15 number of cells. this is what I have so far:
K = 2;
P 1/5;
R = geornd(p,k,1000);
now I am trying to show these result in a histogram with 15 cells but I dont know how to do it please help.
EDIT:
to get the histogram I used:
hist(Sc,15), and this is the results:

According to the doc for geornd, you need to provide the function with a probability parameter P (here 1/5) and a vector dictating the size of the output you want, so it looks like your K is not used correctly in this context.
If you want 1000 random values distributed according to geornd, you might want to use this instead:
R = geornd(0.2,[1 1000]); % P of 0.2 and array of 1 x 1000 numbers
hist(R,15)
Which gives the following:
If you do want do generate 2 distributions, then you can calculate them all at once and plot them separately:
R = geornd(0.2,[2 1000]);
% Plot 1st distribution:
hist(R(1,:),15)
Plot 2nd distribution:
hist(R(2,:),15)

Related

Find the sum of two histograms and plot it

Good day! I have two histograms and I can draw them overlaid on top of one another. But I need to find the sums in each of the columns and plot the summed histogram.
I cannot sum them up because the histogram is built using a function, and you cannot get the values in the column from it.
N = 50; % Total amount
x1 = randn(N,1); % Normally distributed numbers
x2 = rand(N,1)*2; % Normally distributed numbers and shifted
k = -5:0.5:5;
R1 = histogram(x1, k)
hold on
histogram(x2, k)
grid on
Maybe you need [x1,x2] for histogram, e.g.,
histogram([x1,x2],k)
If you have many variables like x1,x2, ..., xN, you can try
histogram(eval(sprintf("[%s]",strjoin(who("x*"),","))),k)

How to use the randn function in Matlab to create an array of values (range 0-10) of size 1,000 that follows a Gaussian distribution? [duplicate]

Matlab has the function randn to draw from a normal distribution e.g.
x = 0.5 + 0.1*randn()
draws a pseudorandom number from a normal distribution of mean 0.5 and standard deviation 0.1.
Given this, is the following Matlab code equivalent to sampling from a normal distribution truncated at 0 at 1?
while x <=0 || x > 1
x = 0.5 + 0.1*randn();
end
Using MATLAB's Probability Distribution Objects makes sampling from truncated distributions very easy.
You can use the makedist() and truncate() functions to define the object and then modify (truncate it) to prepare the object for the random() function which allows generating random variates from it.
% MATLAB R2017a
pd = makedist('Normal',0.5,0.1) % Normal(mu,sigma)
pdt = truncate(pd,0,1) % truncated to interval (0,1)
sample = random(pdt,numRows,numCols) % Sample from distribution `pdt`
Once the object is created (here it is pdt, the truncated version of pd), you can use it in a variety of function calls.
To generate samples, random(pdt,m,n) produces a m x n array of samples from pdt.
Further, if you want to avoid use of toolboxes, this answer from #Luis Mendo is correct (proof below).
figure, hold on
h = histogram(cr,'Normalization','pdf','DisplayName','#Luis Mendo samples');
X = 0:.01:1;
p = plot(X,pdf(pdt,X),'b-','DisplayName','Theoretical (w/ truncation)');
You need the following steps
1. Draw a random value from uniform distribution, u.
2. Assuming the normal distribution is truncated at a and b. get
u_bar = F(a)*u +F(b) *(1-u)
3. Use the inverse of F
epsilon= F^{-1}(u_bar)
epsilon is a random value for the truncated normal distribution.
Why don't you vectorize? It will probably be faster:
N = 1e5; % desired number of samples
m = .5; % desired mean of underlying Gaussian
s = .1; % desired std of underlying Gaussian
lower = 0; % lower value for truncation
upper = 1; % upper value for truncation
remaining = 1:N;
while remaining
result(remaining) = m + s*randn(1,numel(remaining)); % (pre)allocates the first time
remaining = find(result<=lower | result>upper);
end

How to multiply a frequency in histogram by scalar

I am using Matlab for this (preferable idea).
I need to multiply a frequency of a histogram by a scalar value (for each bin).
I have tried this approach in a similar question but it is defined for hist and not histogram function.
This is my original distribution that needs to be multiplied:
This is what I get using the approach given in the similar question:
Additionally, when I finish this part I will have more histograms that I need to sum up into one histogram. So how would I do that? They might have different ranges.
The documentation clearly explains how to replicate the behavior of hist with histogram.
For example:
A = rand(100, 1);
h = histogram(A);
figure
h_new = histogram('BinCounts', h.Values*2, 'BinEdges', h.BinEdges);
Generates the following histograms:
You can modify the Bincounts like this:
X = normrnd(0,1,1000,1); % some data
h = histogram(X,3); % histogram with 3 bins
h.BinCounts = h.Values.*[3 5 1]; % scale each bin by factor 3, 5 and 1 respectively

Computing a moving average

I need to compute a moving average over a data series, within a for loop. I have to get the moving average over N=9 days. The array I'm computing in is 4 series of 365 values (M), which itself are mean values of another set of data. I want to plot the mean values of my data with the moving average in one plot.
I googled a bit about moving averages and the "conv" command and found something which i tried implementing in my code.:
hold on
for ii=1:4;
M=mean(C{ii},2)
wts = [1/24;repmat(1/12,11,1);1/24];
Ms=conv(M,wts,'valid')
plot(M)
plot(Ms,'r')
end
hold off
So basically, I compute my mean and plot it with a (wrong) moving average. I picked the "wts" value right off the mathworks site, so that is incorrect. (source: http://www.mathworks.nl/help/econ/moving-average-trend-estimation.html) My problem though, is that I do not understand what this "wts" is. Could anyone explain? If it has something to do with the weights of the values: that is invalid in this case. All values are weighted the same.
And if I am doing this entirely wrong, could I get some help with it?
My sincerest thanks.
There are two more alternatives:
1) filter
From the doc:
You can use filter to find a running average without using a for loop.
This example finds the running average of a 16-element vector, using a
window size of 5.
data = [1:0.2:4]'; %'
windowSize = 5;
filter(ones(1,windowSize)/windowSize,1,data)
2) smooth as part of the Curve Fitting Toolbox (which is available in most cases)
From the doc:
yy = smooth(y) smooths the data in the column vector y using a moving
average filter. Results are returned in the column vector yy. The
default span for the moving average is 5.
%// Create noisy data with outliers:
x = 15*rand(150,1);
y = sin(x) + 0.5*(rand(size(x))-0.5);
y(ceil(length(x)*rand(2,1))) = 3;
%// Smooth the data using the loess and rloess methods with a span of 10%:
yy1 = smooth(x,y,0.1,'loess');
yy2 = smooth(x,y,0.1,'rloess');
In 2016 MATLAB added the movmean function that calculates a moving average:
N = 9;
M_moving_average = movmean(M,N)
Using conv is an excellent way to implement a moving average. In the code you are using, wts is how much you are weighing each value (as you guessed). the sum of that vector should always be equal to one. If you wish to weight each value evenly and do a size N moving filter then you would want to do
N = 7;
wts = ones(N,1)/N;
sum(wts) % result = 1
Using the 'valid' argument in conv will result in having fewer values in Ms than you have in M. Use 'same' if you don't mind the effects of zero padding. If you have the signal processing toolbox you can use cconv if you want to try a circular moving average. Something like
N = 7;
wts = ones(N,1)/N;
cconv(x,wts,N);
should work.
You should read the conv and cconv documentation for more information if you haven't already.
I would use this:
% does moving average on signal x, window size is w
function y = movingAverage(x, w)
k = ones(1, w) / w
y = conv(x, k, 'same');
end
ripped straight from here.
To comment on your current implementation. wts is the weighting vector, which from the Mathworks, is a 13 point average, with special attention on the first and last point of weightings half of the rest.

generate synthetic data 2d x t x v using matlab

i am trying to generate/simulate a set of synthetic/ simulated data set to generate a synthetic blood flow image in matlab. but i dont know how or where to starts from...
i know i should use the mesh function but how do i make it so it could be in time dimension?
I will be very thankful if anybody could help/ guide me through. I want to generate a data set of size 25x25x10x4. Which is X x Y x t x V. The image should be something similar to this:
or like this:
thank you in advance!
Dataset #1:
Use your favorite line representation (polar, linear, whatever) and randomly generate the parameters for your line. E.g. if you go for y = mx + c, randomly generate m and c. Now that you have defined your line, use this SO method to draw it on the image.
Dataset #2:
They look like 2D Gaussians. Use mvnpdf in the following manner.
[X Y] = meshgrid(x_range,y_range);
Z = reshape( mvnpdf([X(:) Y(:)],MU,SIGMA) ,size(X));
imagesc(Z);
Use some randomly generated MU and SIGMA such that MU lies in x_range and y_range. E.g. x_range = -3:0.1:3;y_range = x_range; and
MU =
0.9575 0.9649
SIGMA =
1.2647 0.3760
0.3760 1.0938
Just to complement #Jacob 's very specific answer, you need a 4D MxNxTxV matrix. In this, according to the post, MxN is the dimension of each image, T is the time dimension, and V is the number of channels or samples per time frame (3 for RGB or >3 for any spectral image).
For each T, generate V images.
Simulate the V images with random parameters for Dataset #1 and Dataset #2.
Put everything in one 4D matrix per Dataset (i.e. using a double for or concatenation)
Replace rand() with generate_image() below, i.e. a function generating random samples of the type of structure you want, according to #Jacob 's suggestions:
M = 25; N = 25;
T = 10; V = 4;
DataSet1 = zeros(M,N,T,V);
DataSet2 = zeros(M,N,T,V);
for t = 1:T
for v = 1:V
DataSet1(:,:,t,v) = randn(M,N);
DataSet2(:,:,t,v) = randn(M,N);
end
end