MatLab - Obtain histogram by column of matrix - matlab

Simply put I have an N x M matrix and I would like to obtain a 256 bin histogram for each column of the matrix. I know how to do this with a for loop, but I need to do it in matrix notation to save valuable computation time.
Also, I would like to use imhist rather than hist.
For loop method:
data = randint(100,100,10);
for n = 1:100
k(:,n) = imhist(data(n,:));
end

hist operates on the column of the input matrix by default. So
>> k = hist( data, 0:255 );
should do the trick for you.

Related

Calculate fft for each column or row in matrix

I have a problem with calculating fft for a signal which is stored in a matrix using matlab. I am trying to calculate fft for each column.
I am trying to do this like this:
for k = 1: ncol
y1(k)= fft(y(:,k));
end
where y is my matrix and and ncol is number of columns in matrix but I'm still getting the following error:
In an assignment A(:) = B, the number of elements in A and B must be the same.
Just do this
y1 = fft(y);
It computes each column separately and it does it much faster than using a for loop.
In response to your original question, you would have to do it like this:
for k = 1: ncol
y1(:,k)= fft(y(:,k));
end
You were trying to put an entire column into a single index which is why you were getting that error message. You need to allocate more room so that the entire column can be stored.
y1 should also be in matrix form. fft of a signal is an array of coefficients

Extracting block diagonal from matrix

I have an njxnj matrix made up of nxn matrices. I want to extract the diagonal j blocks of nxn matrices. i.e. I want to extract the diagonal (for n = 2, j = 4):
What would be the most efficient way of doing this?
To index the elements you can use blkdiag to create a corresponding mask.
%your parameters
n=2
j=4
%some example matrix
M=magic(n*j);
%create the input for blkdiag, j matrices of size n
h=repmat({true(n)},j,1)
%use blkdiag to select the elements
M(logical(blkdiag(h{:})))
For large j, this answer of #Daniel becomes slow. I would instead recommend using linear indices of block diagonal.
n=2;
j=4;
%some example matrix
M=magic(n*j);
linIndices = (0:n*((n*j)+1):n*((n*j)+1)*(j-1))+reshape((1:n)'+n*j*(0:n-1),[],1);
newM = reshape(M(linIndices),n,n,[]);

Generating dataset with mean, std dev, and number of samples

I am trying to generate a 2D data set with the following parameters:
x= N(-5,1) y= N(0,1) n= 1000
Where N(mean, std dev) and n = number of samples.
I tried:
x = normrnd(-5, 1, [100,10])
y = normrnd(0,1,[100,10])
to generate a 100 x 10 array with the appropriate values. I now need to find a way to output the values from these two arrays into an N(x,y) format that can be analyzed by Weka. Any suggestions on how to do this would be appreciated.
Given your comments, you want to generate a N x 2 matrix where each row is a pair of values that both come from different normal distributions.
You can either generate the 2D matrices of each separately and unroll them into single vectors and concatenate them both.... or the simplest way is to just generate 100 x 10 = 1000 elements in a 1D vector from each distribution and concatenate these together.
Method #1 - 2D matrix unrolling
x = normrnd(-5, 1, [100,10]);
y = normrnd(0, 1, [100,10]);
N = [x(:) y(:)];
Method #2 - 1D vector concatenation
x = normrnd(-5, 1, [1000,1]); %// Change
y = normrnd(0, 1, [1000,1]); %// Change
N = [x y];
If you wish to write this to a CSV file, where you have a pair of x,y values separated by a comma and you have Class_A at the end, a call to fopen to open up a file for writing, fwrite to write our stuff to the file and fclose to finally close the file is needed. You also require that the digits are 3 digits of precision. Something like this comes to mind:
f = fopen('numbers.csv', 'w'); %// Open up the file
fprintf(f,'%.3f,%.3f,Class_A\n', N.'); %'// Write the data
fclose(f); %// Close the file
It's important to look at the second statement carefully. Note that I'm writing the transpose of N because MATLAB writes values in column-major order. This means that if you want the rows to be written to the file, you have to transpose the matrix to do that. numbers.csv is what the file is called when it is written. If you examine this file now, you'll see that it's in the form of x,y,Class_A where x,y is a pair of values from both normal distributions.
You can use mvnrnd(mu_vector, sigma_matrix)
mu = [-5;0];
Sigma = [1,0;0,1];
n = 1000;
X = mvnrnd(mu, Sigma, n);

Storing output from each for loop iteration in MATLAB

Say I have 3 matrix data files in a folder..
I have a function (clustering_coef_bu) which calculates the clustering coefficient of a 2D matrix (data; has the dimensions 512x512) file. The output vector of the function creates a 512x1 Matrix (Clustering Coefficient), in double format.
With the for loop below, for each matrix (data) I'm calculating the clustering coefficient. However, I am having difficulties being able to store the output clustering coefficient for each run of the for loop. It would be ideal to output the clustering coefficient of each matrix into one singular structure. I.e a cell array, which has the dimensions 512x3.
for k = 1:3
ClusteringCoefficient=clustering_coef_bu(data)
end
Any help would be great. Thanks.
Something like this would probably help you:
widthArray = 3;
ClustingeringCoefficient = zeros(size(data, 1), widthArray);
for k = 1:widthArray
ClusteringCoefficient(:, k) = clustering_coef_bu(data); % a 512x3 double matrix
end

How do I create a simliarity matrix in MATLAB?

I am working towards comparing multiple images. I have these image data as column vectors of a matrix called "images." I want to assess the similarity of images by first computing their Eucledian distance. I then want to create a matrix over which I can execute multiple random walks. Right now, my code is as follows:
% clear
% clc
% close all
%
% load tea.mat;
images = Input.X;
M = zeros(size(images, 2), size (images, 2));
for i = 1:size(images, 2)
for j = 1:size(images, 2)
normImageTemp = sqrt((sum((images(:, i) - images(:, j))./256).^2));
%Need to accurately select the value of gamma_i
gamma_i = 1/10;
M(i, j) = exp(-gamma_i.*normImageTemp);
end
end
My matrix M however, ends up having a value of 1 along its main diagonal and zeros elsewhere. I'm expecting "large" values for the first few elements of each row and "small" values for elements with column index > 4. Could someone please explain what is wrong? Any advice is appreciated.
Since you're trying to compute a Euclidean distance, it looks like you have an error in where your parentheses are placed when you compute normImageTemp. You have this:
normImageTemp = sqrt((sum((...)./256).^2));
%# ^--- Note that this parenthesis...
But you actually want to do this:
normImageTemp = sqrt(sum(((...)./256).^2));
%# ^--- ...should be here
In other words, you need to perform the element-wise squaring, then the summation, then the square root. What you are doing now is summing elements first, then squaring and taking the square root of the summation, which essentially cancel each other out (or are actually the equivalent of just taking the absolute value).
Incidentally, you can actually use the function NORM to perform this operation for you, like so:
normImageTemp = norm((images(:, i) - images(:, j))./256);
The results you're getting seem reasonable. Recall the behavior of the exp(-x). When x is zero, exp(-x) is 1. When x is large exp(-x) is zero.
Perhaps if you make M(i,j) = normImageTemp; you'd see what you expect to see.
Consider this solution:
I = Input.X;
D = squareform( pdist(I') ); %'# euclidean distance between columns of I
M = exp(-(1/10) * D); %# similarity matrix between columns of I
PDIST and SQUAREFORM are functions from the Statistics Toolbox.
Otherwise consider this equivalent vectorized code (using only built-in functions):
%# we know that: ||u-v||^2 = ||u||^2 + ||v||^2 - 2*u.v
X = sum(I.^2,1);
D = real( sqrt(bsxfun(#plus,X,X')-2*(I'*I)) );
M = exp(-(1/10) * D);
As was explained in the other answers, D is the distance matrix, while exp(-D) is the similarity matrix (which is why you get ones on the diagonal)
there is an already implemented function pdist, if you have a matrix A, you can directly do
Sim= squareform(pdist(A))