create a Correct histogram - matlab

I have a range of data represented in the vector C
and have the data classes represented by the vector R
C = [1.71974522292994
1.91974522292994
2.03821656050955
2.13375796178344
2.16560509554140
2.22929936305733
2.35668789808917
2.38853503184713
2.54777070063694
2.61146496815287
2.70700636942675
2.73885350318471
2.83439490445860
2.96178343949045
3.02547770700637
3.31210191082803]
R = [1.71974522292994
2.03821104580359
2.35667686867724
2.67514269155088
2.99360851442453
3.31207433729818
3.63054016017183]
I need to do a histogram and a curve to overlap Standard Normal
z = histc(C,R); bar(R,z);
but the vector z that represents the frequency is not correct.
z = [2 4 4 4 1 1]'
on excell is so, and represents well the histogram
z = [1 1 4 4 4 1 1]'
you could suggest a solution using these two vectors?
Tnks

That's because Matlab's definition of histc:
n(k) counts the value x(i) if edges(k) <= x(i) < edges(k+1)
whereas Excel probably uses the more standard
edges(k) < x(i) <= edges(k+1)
So essentially you need to move the equal sign from below to above. You can get that either
By the trick of changing signs to both vectors and flipping the second (to keep it sorted):
>> z = histc(-C,-R(end:-1:1))
z =
1
1
4
4
4
1
1
Using the very powerful bsxfun function to directly compute the histogram with the equal sign above:
z = diff(sum(bsxfun(#le, C(:), [-inf R(:).'])));

I found it helpful to use this
z = histc(-C,-R);
the loop that I used for inside includes matrices with vectors of different length. I then filled the matrix with NaN
C and classe = [30x14] created by vectors with different lengths + NaN
[nr,nc] = size(C);
Freq = NaN*ones(nr,nc);
R = NaN*ones(nr,nc);
CC = NaN*ones(nr,nc);
I do not find a way in order to create the correct number of figures with the correct subplot.
In each figure there must be 4 subplot.
for k = 1:4
for j= 1 : nc;
R = classe(:,j);
CC = C(:,j);
FF = Freq(:,j);
R = R(~isnan(B)); % toglie i valori NaN
CC = CC(~isnan(CC));
R = sort(R,'descend');
CC = sort(C,'descend');
the line of Plot
FF = histc(-C,-R); % Calculate the J-th absolute frequencies
figure(k); <===?????
subplot(2,2,k) <=== ????????
bar(B,FF);
reassemble the matrices
if length(B)<nr
R(length(R)+1:nr)=NaN; % riempie la parte di colonna vuota
if length(CC)< nr;
C(length(CC)+1:nr)=NaN;
if length(FF)< nr;
FF(length(FF)+1:nr)=NaN;
end
end
end
classe(:,j)=R(:); % matrice classe
C(:,j)=CC(:) % matrice Elementi;
Freq(:,j)=FF(:); %Matrice Frequenze Assolute
end
the next steps concerns the in plotting of 3 figures. Each figure contains 4 subplot
I would also be able to superimpose on each histogram a standard normal curve ...
a tip?
tnks

Related

Add a diagonal of zeros to a matrix in MATLAB

Suppose I have a matrix A of dimension Nx(N-1) in MATLAB, e.g.
N=5;
A=[1 2 3 4;
5 6 7 8;
9 10 11 12;
13 14 15 16;
17 18 19 20 ];
I want to transform A into an NxN matrix B, just by adding a zero diagonal, i.e.,
B=[ 0 1 2 3 4;
5 0 6 7 8;
9 10 0 11 12;
13 14 15 0 16;
17 18 19 20 0];
This code does what I want:
B_temp = zeros(N,N);
B_temp(1,:) = [0 A(1,:)];
B_temp(N,:) = [A(N,:) 0];
for j=2:N-1
B_temp(j,:)= [A(j,1:j-1) 0 A(j,j:end)];
end
B = B_temp;
Could you suggest an efficient way to vectorise it?
You can do this with upper and lower triangular parts of the matrix (triu and tril).
Then it's a 1 line solution:
B = [tril(A,-1) zeros(N, 1)] + [zeros(N,1) triu(A)];
Edit: benchmark
This is a comparison of the loop method, the 2 methods in Sardar's answer, and my method above.
Benchmark code, using timeit for timing and directly lifting code from question and answers:
function benchie()
N = 1e4; A = rand(N,N-1); % Initialise large matrix
% Set up anonymous functions for input to timeit
s1 = #() sardar1(A,N); s2 = #() sardar2(A,N);
w = #() wolfie(A,N); u = #() user3285148(A,N);
% timings
timeit(s1), timeit(s2), timeit(w), timeit(u)
end
function sardar1(A, N) % using eye as an indexing matrix
B=double(~eye(N)); B(find(B))=A.'; B=B.';
end
function sardar2(A,N) % similar to sardar1, but avoiding slow operations
B=1-eye(N); B(logical(B))=A.'; B=B.';
end
function wolfie(A,N) % using triangular parts of the matrix
B = [tril(A,-1) zeros(N, 1)] + [zeros(N,1) triu(A)];
end
function user3285148(A, N) % original looping method
B = zeros(N,N); B(1,:) = [0 A(1,:)]; B(N,:) = [A(N,:) 0];
for j=2:N-1; B(j,:)= [A(j,1:j-1) 0 A(j,j:end)]; end
end
Results:
Sardar method 1: 2.83 secs
Sardar method 2: 1.82 secs
My method: 1.45 secs
Looping method: 3.80 secs (!)
Conclusions:
Your desire to vectorise this was well founded, looping is way slower than other methods.
Avoiding data conversions and find for large matrices is important, saving ~35% processing time between Sardar's methods.
By avoiding indexing all together you can save a further 20% processing time.
Generate a matrix with zeros at diagonal and ones at non-diagonal indices. Replace the non-diagonal elements with the transpose of A (since MATLAB is column major). Transpose again to get the correct order.
B = double(~eye(N)); %Converting to double since we want to replace with double entries
B(find(B)) = A.'; %Replacing the entries
B = B.'; %Transposing again to get the matrix in the correct order
Edit:
As suggested by Wolfie for the same algorithm, you can get rid of conversion to double and the use of find with:
B = 1-eye(N);
B(logical(B)) = A.';
B = B.';
If you want to insert any vector on a diagonal of a matrix, one can use plain indexing. The following snippet gives you the indices of the desired diagonal, given the size of the square matrix n (matrix is n by n), and the number of the diagonal k, where k=0 corresponds to the main diagonal, positive numbers of k to upper diagonals and negative numbers of k to lower diagonals. ixd finally gives you the 2D indices.
function [idx] = diagidx(n,k)
% n size of square matrix
% k number of diagonal
if k==0 % identity
idx = [(1:n).' (1:n).']; % [row col]
elseif k>0 % Upper diagonal
idx = [(1:n-k).' (1+k:n).'];
elseif k<0 % lower diagonal
idx = [(1+abs(k):n).' (1:n-abs(k)).'];
end
end
Usage:
n=10;
k=3;
A = rand(n);
idx = diagidx(n,k);
A(idx) = 1:(n-k);

Create vector of inner vectors with elementwise subtracted elements for plotting (Matlab)

I am running a program where at each time loop I obtain a N dim. vector v(t).
At the end of the program, I want to obtain a vector (or array?) which contains vectors from each iteration that is created by taking each element of v(t) and subtracting it will all other elements. However I am only interested in the absolute difference of the elements.
Therefore, if I let u denote the vector with subtracted elements at some arbitrary iteration, I want for instance that u(1)(t_0) = v_1(t_0) - v_2(t_0) but I don't also need u(k) = v_2(t_0) - v_1(t_0) for some index k
At each iteration t I also create a time vector Time(end+1) = t.
At the end I obtain a vector of vectors: [u_1, u_2, u_3,...] and a time vector Time = [t_1 , t_2 , ...] and I want to plot [u_1(i), u_2(i) , ...] against Time for all i in the same plot.
Here is a small example:
T = 400
dt = 1e-1
u = [];
Time = [];
v = [0; 0; 0; 0;];
for t = 0:dt:T
v = v + func(t)
Y = subtractFunc(v) % I am looking for help to create this subtractFunc..
Time(end+1) = t;
u(end+1) = Y;
end
% ... And help to create the properplot command, below code not appropriate
plot(u,Time)
To sum it up: How do I create subtractFunc (or a some inline command) that takes creates a new vector Y containing the absolute difference between each pair of elements in v?
And how do I then go about and plot all the differences in u at each time against the time vector Time?
You can use MATLAB diff to take pairwise differences, then take the absolute value:
>> v = [1 3 6 -2 6]; %% random values
>> diff(v)
ans =
2 3 -8 8
>> abs(diff(v))
ans =
2 3 8 8

surface plot in Matlab

I am trying to graph a surface with a diagonal matrix, the equation I am trying graph is f = x^TDx, x is a 2 by 1 vector and D is a 2 by 2 matrix.
Here is what have so far, but I keep getting error.
x = linspace(-10,10);
y = linspace(-10,10);
[X,Y] = meshgrid(x,y);
D = [1 0; 0 1];
f = #(x,y) [x,y]*D*[x,y].'; % [x,y] is 1 by 2
contour (X,Y,f(X,Y))
Can someone tell me how to get rid of the error? Thanks
Since x and y have the same length, your diagonal matrix D must be a square matrix of size n x n, with n equal to two times the length of your x or y vectors. The reason why you need to multiply the length by two is because the operation [x,y] concatenates the arrays horizontally thus duplicating one of the dimensions.
In this example D is the Identity matrix. See eye for more information.
x = linspace(-10,10); % x is 1x100
y = linspace(-10,10); % y is 1x100
[X,Y] = meshgrid(x,y); % X is 100x100 and Y is 100x100
D = eye(2*numel(x)); % D is 2*100x2*100 = 200x200
f = #(x,y) [x,y]*D*[x,y].'; % [X,Y] is 100x200 and [X,Y].' is 200x100
contour (X,Y,f(X,Y))
If you want D to be a random diagonal matrix, you can accomplish this combining diag with one of the Random Number Generation functions available, like for example randn.
On the previous example, replace D with the following instruction:
D = diag(randn(1,2*numel(x)));
You can also give the coefficients you choose to the diagonal matrix. To do so, you will need to create the vector of coefficients manually, making sure that it has the adequate length, so that it satisfies the conditions explained at the beginning of this post.
Try now replacing D with the following instructions:
v = 1:2*numel(x); % vector of coefficients: v = [1 2 ... 200]
D = diag(v);

How to implement a piecewise function and then plot it on certain intervals in MATLAB

I am actually attempting to write code for the cubic spline interpolation. Cubic spline boils down to a series of n-1 segments where n is the number of original coordinates given initially and the segments are each represented by some cubic function.
I have figured out how to get all the coefficients and values for each segment, stored in vectors a,b,c,d, but I don't know how to plot the function as a piecewise function on different intervals. Here is my code so far. The very last for loop is where I have attempted to plot each segment.
%initializations
x = [1 1.3 1.9 2.1 2.6 3.0 3.9 4.4 4.7 5.0 6 7 8 9.2 10.5 11.3 11.6 12 12.6 13 13.3].';
y = [1.3 1.5 1.85 2.1 2.6 2.7 2.4 2.15 2.05 2.1 2.25 2.3 2.25 1.95 1.4 0.9 0.7 0.6 0.5 0.4 0.25].';
%n is the amount of coordinates
n = length(x);
%solving for a-d for all n-1 segments
a = zeros(n,1);
b = zeros(n,1);
d = zeros(n,1);
%%%%%%%%%%%%%% SOLVE FOR a's %%%%%%%%%%%%%
%Condition (b) in Definition 3.10 on pg 146
%Sj(xj) = f(xj) aka yj
for j = 1: n
a(j) = y(j);
end
%initialize hj
h = zeros(n-1,1);
for j = 1: n-1
h(j) = x(j+1) - x(j);
end
A = zeros(n,n);
bv = zeros(n,1); %bv = b vector
%initialize corners to 1
A(1,1) = 1;
A(n,n) = 1;
%set main diagonal
for k = 2: n-1
A(k,k) = 2*(h(k-1) + h(k));
end
%set upper and then lower diagonals
for k = 2 : n-1
A(k,k+1) = h(k); %h2, h3, h4...hn-1
A(k,k-1) = h(k-1); %h1, h2, h3...hn
end
%fill up the b vector using equation in notes
%first and last spots are 0
for j = 2 : n-1
bv(j) = 3*(((a(j+1)-a(j)) / h(j)) - ((a(j) - a(j-1)) / h(j-1)));
end
%augmented matrix
A = [A bv];
%%%%%%%%%%%% BEGIN GAUSSIAN ELIMINATION %%%%%%%%%%%%%%%
offset = 1;
%will only need n-1 iterations since "first" pivot row is unchanged
for k = 1: n-1
%Searching from row p to row n for non-zero pivot
for p = k : n
if A(p,k) ~= 0;
break;
end
end
%row swapping using temp variable
if p ~= k
temp = A(p,:);
A(p,:) = A(k,:);
A(k,:) = temp;
end
%Eliminations to create Upper Triangular Form
for j = k+1:n
A(j,offset:n+1) = A(j,offset:n+1) - ((A(k, offset:n+1) * A(j,k)) / A(k,k));
end
offset = offset + 1;
end
c = zeros(n,1); %initializes vector of data of n rows, 1 column
%Backward Subsitution
%First, solve the nth equation
c(n) = A(n,n+1) / A(n,n);
%%%%%%%%%%%%%%%%% SOLVE FOR C's %%%%%%%%%%%%%%%%%%
%now solve the n-1 : 1 equations (the rest of them going backwards
for j = n-1:-1:1 %-1 means decrement
c(j) = A(j,n+1);
for k = j+1:n
c(j) = c(j) - A(j,k)*c(k);
end
c(j) = c(j)/A(j,j);
end
%%%%%%%%%%%%% SOLVE FOR B's and D's %%%%%%%%%%%%%%%%%%%%
for j = n-1 : -1 : 1
b(j) = ((a(j+1)-a(j)) / h(j)) - (h(j)*(2*c(j) + c(j+1)) / 3);
d(j) = (c(j+1) - c(j)) / 3*h(j);
end
%series of equation segments
for j = 1 : n-1
f = #(x) a(j) + b(j)*(x-x(j)) + c(j)*(x-x(j))^2 + d(j)*(x-x(j))^3;
end
plot(x,y,'o');
Let's assume that I have calculated vectors a,b,c,d correctly for each segment. How do I plot each cubic segment such that they all appear graphed on a single plot?
I appreciate the help.
That's pretty easy. You've already done half of the work by defining an anonymous function that is for the cubic spline in between each interval. However, you need to make sure that the operations in the function are element-wise. You currently have it operating on scalars, or assuming that we are using matrix operations. Don't do that. Use .* instead of * and .^ instead of ^. The reason why you need to do this is to make generating the points on the spline a lot easier, where my next point follows.
All you have to do next is define a bunch of x points within the interval defined by the neighbouring x key points and substitute them into your function, then plot the result.... so something like this:
figure;
hold on;
for j = 1 : n-1
f = #(x) a(j) + b(j).*(x-x(j)) + c(j).*(x-x(j)).^2 + d(j)*(x-x(j)).^3; %// Change function to element-wise operations - be careful
x0 = linspace(x(j), x(j+1)); %// Define set of points
y0 = f(x0); %// Find output points
plot(x0, y0, 'r'); %// Plot the line in between the key points
end
plot(x, y, 'bo');
We spawn a new figure, then use hold on so that when we call plot multiple times, we append the results to the same figure. Next, for each set of cubic spline coefficients we have, define a spline function, then generate a bunch of x values with linspace that are between the current x key point and the one beside it. By default, linspace generates 100 points between a start point (i.e. x(j)) and end point (i.e. x(j+1)). You can control how many points you want to generate by specifying a third parameter (so something like linspace(x(j), x(j+1), 25); to generate 25 points). We use these x values and substitute them into our spline equation to get our y values. We then plot this result on the figure using a red line. Once we're done, we plot the key points as blue open circles on top of the curve.
As a bonus, I ran your code with the above plotting mechanism, and this is what I get:

Getting the N-dimensional product of vectors

I am trying to write code to get the 'N-dimensional product' of vectors. So for example, if I have 2 vectors of length L, x & y, then the '2-dimensional product' is simply the regular vector product, R=x*y', so that each entry of R, R(i,j) is the product of the i'th element of x and the j'th element of y, aka R(i,j)=x(i)*y(j).
The problem is how to elegantly generalize this in matlab for arbitrary dimensions. This is I had 3 vectors, x,y,z, I want the 3 dimensional array, R, such that R(i,j,k)=x(i)*y(j)*z(k).
Same thing for 4 vectors, x1,x2,x3,x4: R(i1,i2,i3,i4)=x1(i1)*x2(i2)*x3(i3)*x4(i4), etc...
Also, I do NOT know the number of dimensions beforehand. The code must be able to handle an arbitrary number of input vectors, and the number of input vectors corresponds to the dimensionality of the final answer.
Is there any easy matlab trick to do this and avoid going through each element of R specifically?
Thanks!
I think by "regular vector product" you mean outer product.
In any case, you can use the ndgrid function. I like this more than using bsxfun as it's a little more straightforward.
% make some vectors
w = 1:10;
x = w+1;
y = x+1;
z = y+1;
vecs = {w,x,y,z};
nvecs = length(vecs);
[grids{1:nvecs}] = ndgrid(vecs{:});
R = grids{1};
for i=2:nvecs
R = R .* grids{i};
end;
% Check results
for i=1:10
for j=1:10
for k=1:10
for l=1:10
V(i,j,k,l) = R(i,j,k,l) == w(i)*x(j)*y(k)*z(l);
end;
end;
end;
end;
all(V(:))
ans = 1
The built-in function bsxfun is a fast utility that should be able to help. It is designed to perform 2 input functions on a per-element basis for two inputs with mismatching dimensions. Singletons dimensions are expanded, and non-singleton dimensions need to match. (It sounds confusing, but once grok'd it useful in many ways.)
As I understand your problem, you can adjust the dimension shape of each vector to define the dimension that it should be defined across. Then use nested bsxfun calls to perform the multiplication.
Example code follows:
%Some inputs, N-by-1 vectors
x = [1; 3; 9];
y = [1; 2; 4];
z = [1; 5];
%The computation you describe, using nested BSXFUN calls
bsxfun(#times, bsxfun(#times, ... %Nested BSX fun calls, 1 per dimension
x, ... % First argument, in dimension 1
permute(y,2:-1:1) ) , ... % Second argument, permuited to dimension 2
permute(z,3:-1:1) ) % Third argument, permuted to dimension 3
%Result
% ans(:,:,1) =
% 1 2 4
% 3 6 12
% 9 18 36
% ans(:,:,2) =
% 5 10 20
% 15 30 60
% 45 90 180
To handle an arbitrary number of dimensions, this can be expanded using a recursive or loop construct. The loop would look something like this:
allInputs = {[1; 3; 9], [1; 2; 4], [1; 5]};
accumulatedResult = allInputs {1};
for ix = 2:length(allInputs)
accumulatedResult = bsxfun(#times, ...
accumulatedResult, ...
permute(allInputs{ix},ix:-1:1));
end