histogram in matlab but without using hist function - matlab

I'm a little bit stuck on how to plot a histogram in MatLab without using hist function
the question is that
Generate a random number between (0 ,100) and plot 1000 of those random digits on xy,plan as histogram
example
let interval is 10
x | y
0 -10 | 5
10-20 | 9
20-30 | 15
etc ...
where x is interval and y represent the repeated random number in that interval
I try to write this code
function []=drawhist(a,b)
x=a+(b-a)*rand(1,1000);
bar(x)
end
but not give me the output desired , please help me with any idea to understand how to write this function

This should do what you want, however this is for integers.
If you want this to generalise to flots you need to define the accuracy of sampling and define edges that are half that accuracy
function [centers,freq] = drawhist(range,interval,density)
% example
% generate 1000 random integers ranging between 0 and 100;
% drawhist([0,100],10,1000);
V = randi([0,100],density,1);
min_x = range(1); max_x = range(2);
bin = linspace(min_x,max_x,interval+1);
freq = zeros(interval,1);
for ii=1:interval
freq(ii) = sum(V>bin(ii)&V<bin(ii+1));
end
centers = bin(2:end)-(bin(2:end)-bin(1:end-1))/2;
bar(centers,freq);
end
Enjoy

Related

Generating larger random integers - MATLAB

Trying to assign appropriate value to x that would result in random integers between 1 to 60. Any suggestions? I did randn but am getting small numbers over and over. Here's the code so far:
function s = Q11sub1(x)
x = % <------ Question is what goes here
if x <= 30
s = "small";
elseif x > 30 & x <= 50
s = "medium";
else
s = "high";
end
end
Use randi:
randi(60)
This will give you a pseudorandom integer between 1 to 60.
Reference: https://www.mathworks.com/help/matlab/ref/randi.html
The problem is randn generates random numbers that follow a standard Normal distribution, e.g. Normal(mu = 0, std = 1).
As #Banghua Zhao points out, you want the randi function and I'll add they will be uniformly distributed across the integers (inclusively) between those integer bounds (known as the discrete uniform distribution).
The code X = randi([a b],N,M) will generate a NxM matrix of integers uniformly distributed on the interval [a,b] inclusively. A call randi(Imax) defaults the lower bound to 1.
See the difference below.
N = 500; % Number of samples
a = 1; % Lower integer bound
b = 60; % Upper integer bound
X = randi([a b],N,1); % Random integers between [a,b]
Y = randn(N,1);
figure, hold on, box on
histogram(X)
histogram(Y)
legend('randi[1,60]','randn','Location','southeast')
xlabel('Result')
ylabel('Observed Frequency')
title({'randi([a b],N,1) vs randn(N,1)';'N = 500'})
EDIT: At #Max's suggestion, I've added 60*randn.
% MATLAB R2017a
W = 60*randn(N,1);
figure, hold on, box on
hx = histogram(X,'Normalization','pdf')
hw = histogram(W,'Normalization','pdf')
legend('randi[1,60]','60*randn','Location','southeast')
xlabel('Result')
ylabel('Observed Estimated Density')
title({'randi([a b],N,1) vs 60*randn(N,1)';['N = ' num2str(N)]})

compute the average over simulation for different parameters values

I am working on something similar to the following example:
I want to compute <x(t)> that is the average of a function x(t) over number of simulations. To do this, I generate the following code:
sim=50;% number of simulations
t=linspace(0,1);% time interval
a_range=[1,2,3];% different values for the parameter a
b_range=[0,0.5,1];% different values for the parameter b
z=zeros(1,sim);
theta=zeros(1,sim);
for nplot=1:3
a=a_range(nplot);
b=b_range(nplot);
average_x=zeros(nplot,sim);
for i=1:sim
z(i)=rand(1);% random number for every simulation
theta(i)=pi*rand(1);% random number for every simulation
x=z(i)*t.^2+a*sin(theta(i))+b.*tan(theta(i));% the function
end
average_x(nplot,sim)=mean(x);% average over the number of simulations
end
fname=['xsin.mat'];
save(fname)
The time is a vector 1 by 100 and x is a vector 1 by 100, and average_x is 1 by 50. What I am looking for is to write a script to load the file and plot the average against time for different parameters a and b. So I want to write a code to generate three figures such that in figure 1 I will plot the average
plot(t,average_x)
for a=1 and b=0.
Then in figure 2 I will plot the average again but for a=2 and b=0.5 and so on. The problem is the dimension of time t and the average are not the same. How can I fix this problem and generate three distinct figures.
If I got your intention correctly, this is what you look for:
sim = 50;% number of simulations
t = linspace(0,1);% time interval
a_range = [1,2,3];% different values for the parameter a
b_range = [0,0.5,1];% different values for the parameter b
% NO NEED TO GENERATE THE RANDOM NUMBERS ONE BY ONE:
theta = pi*rand(sim,1);% random number for every simulation
z = rand(sim,1); % random number for every simulation
% YOU SOULD INITIALIZE ALL YOUR VARIABLES OUTSIDE THE LOOPS:
x = zeros(sim,numel(t));
average_x = zeros(3,numel(t));% the mean accross simulations
% for average accros time use:
% average_x = zeros(3,sim);
for nplot=1:3
a = a_range(nplot);
b = b_range(nplot);
for i=1:sim
x(i,:) = z(i)*t.^2+a*sin(theta(i))+b.*tan(theta(i));% the function
end
average_x(nplot,:) = mean(x); % average over the number of simulations
% average_x(nplot,:) = mean(x,2); % average accross time
end
% save the relevant variables:
save('results.mat','average_x','t')
In another file you can write:
load('results.mat')
for k = 1:size(average_x,1)
figure(k)
plot(t,average_x(k,:))
title(['Parameter set ' num2str(k)])
xlabel('Time')
ylabel('mean x')
end
This is the plot in one figure (if you want then average over simulations):
BTW, if you want to make your code more compact and fast, you can vectorize it, mainly using bsxfun. Here is a demonstration with your code:
% assuming all parameters are defined as above:
zt = bsxfun(#times,z,t.^2); % first part of the function 'z(i)*t.^2'
% second part of the function 'a*sin(theta(i)) + b.*tan(theta(i))':
ab = bsxfun(#times,a_range,sin(theta)) + bsxfun(#times,b_range,tan(theta));
% convert the second part to the right dimensions and size:
ab = repmat(reshape(ab,[],1,3),1,numel(t),1);
x = bsxfun(#plus,zt,ab); % the function
average_x = squeeze(mean(x)); % take the mean by simulation
plot(t,average_x) % plot it all at once, as in the figure above
xlabel('Time')
ylabel('mean x')

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

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)

Sequentially reading down a matrix column in MATLAB

My original problem was to create a scenario whereby there is a line of a specific length (x=100), and a barrier at specific position (pos=50). Multiple rounds of sampling are carried out, within which a specific amount of random numbers (p) are made. The numbers generated can either fall to left or right of the barrier. The program outputs the difference between the largest number generated to the left of the barrier and the smallest number generated to the right. This is much clearer to see here:
In this example, the system has created 4 numbers (a,b,c,d). It will ignore a and d and output the difference between b and c. Essentially, it will output the smallest possible fragment of the line that still contains the barrier.
The code I have been using to do this is:
x = 100; % length of the grid
pos = 50; % position of the barrier
len1 = 0; % left edge of the grid
len2 = x; % right edge of the grid
sample = 1000; % number of samples to make
nn = 1:12 % number of points to generate (will loop over these)
len = zeros(sample, length(nn)); % array to record the results
for n = 1:length(nn) % For each number of pts to generate
numpts = nn(n);
for i = 1:sample % For each round of sampling,
p = round(rand(numpts,1) * x); % generate 'numpts' random points.
if any(p>pos) % If any are to the right of the barrier,
pright = min(p(p>pos)); % pick the smallest.
else
pright = len2;
end
if any(p<pos) % If any are to the left of the barrier,
pleft = max(p(p<pos)); % pick the largest.
else
pleft = len1;
end
len(i,n) = pright - pleft; % Record the length of the interval.
end
end
My current problem: I'd like to make this more complex. For example, I would like to be able to use more than just one random number count in each round. Specifically I would like to relate this to Poisson distributions with different mean values:
% Create poisson distributions for λ = 1:12
range = 0:20;
for l=1:12;
y = poisspdf(range,l);
dist(:,l) = y;
end
From this, i'd like to take 1000 samples for each λ but within each round of 1000 samples, the random number count is no longer the same for all 1000 samples. Instead it depends on the poisson distribution. For example, within a mean value of 1, the probabilities are:
0 - 0.3678
1 - 0.3678
2 - 0.1839
3 - 0.0613
4 - 0.0153
5 - 0.0030
6 - 0.0005
7 - 0.0001
8 - 0.0000
9 - 0.0000
10 - 0.0000
11 - 0.0000
12 - 0.0000
So for the first round of 1000 samples, 367 of them would be carried out generating just 1 number, 367 carried out generating 2 numbers, 183 carried out generating 3 numbers and so on. The program will then repeat this using new values it gains from a mean value of 2 and so on. I'd then like to simply collect together all the fragment sizes (pright-pleft) into a column of a matrix - a column for each value of λ.
I know I could do something like:
amount = dist*sample
To multiply the poisson distributions by the sample size to gain how many of each number generation it should do - however i'm really stuck on how to incorporate this into the for-loop and alter the code to meet to tackle this new problem. I am also not sure how to read down a column on a matrix to use each probability value to determine how much of each type of RNG it should do.
Any help would be greatly appreciated,
Anna.
You could generate a vector of random variables from a known pdf object using random, if you have the statistics toolbox. Better still, skip the PDF step and generate the random variables using poissrnd. Round off the value to the nearest integer and call rand as you were doing already. In your loop simply iterate over your generated vector of poisson distributed random numbers.
Example:
x = 100; % length of the grid
pos = 50; % position of the barrier
len1 = 0; % left edge of the grid
len2 = x; % right edge of the grid
sample = 1000; % number of samples to make
lambda = 1:12; % lambdas
Rrnd = round(poissrnd(repmat(lambda,sample,1)));
len = zeros(size(Rrnd)); % array to record the results
for n = lambda; % For each number of pts to generate
for i = 1:sample % For each round of sampling,
numpts = Rrnd(i,n);
p = round(rand(numpts,1) * x); % generate 'numpts' random points.
len(i,n) = min([p(p>pos);len2]) - max([p(p<pos);len1]); % Record the length
end
end

exponential random numbers with a bound in matlab

I want to pick values between, say, 50 and 150 using an exponential random number generator (a flat hazard function). How do I implement bounds on the built-in exponential random number function in matlab?
A quick way is to a sequence longer than you need, and throw out values outside your desired range.
dist = exprnd(100,1,1000);
%# mean of 100 ---^ ^---^--- 1x1000 random numbers
dist(dist<50 | dist>150) = []; %# will be shorter than 1000
If you don't have enough values after pruning, you can repeat and append onto the vector, or however else you want to do it.
exprandn uses rand (see >> open exprnd.m) so you can bound the output of that instead by reversing the process and sampling uniformly within the desired range [r1, r2].
sizeOut = [1, 1000]; % sample size
mu = 100; % parameter of exponential
r1 = 50; % lower bound
r2 = 150; % upper bound
r = exprndBounded(mu, sizeOut, r1, r2); % bounded output
function r = exprndBounded(mu, sizeOut, r1, r2);
minE = exp(-r1/mu);
maxE = exp(-r2/mu);
randBounded = minE + (maxE-minE).*rand(sizeOut);
r = -mu .* log(randBounded);
The drawn densities (using a non-parametric kernel estimator) look like the following for 20K samples