Plot the density of a matrix - matlab

Good day,
In Matlab I have got a matrix which is very sparse. Now I would like to plot the 'density' of the matrix. Let's say I have a matrix A:
A = [3 0 0
0 2 0
0 0 1];
Now the plot should look something like:
x
x
x
So there should be a dot (or something else) at each location (row, column) in which matrix A has got a nonzero value.
Any ideas?

spy is what you need:
% taken from MatLab documentation
B = bucky;
spy(B)

Consider something like this:
subs = zeros(0,2);
for ind = [find(A)']
[r,c] = ind2sub(size(A), ind);
subs = [subs; [r,c]];
end
scatter(subs(:,2), subs(:,1));
set(gca,'YDir','Reverse')
xlim([1 size(A,2)])
ylim([1 size(A,1)])
Which, for the matrix A:
0 1 0 1 1
0 0 0 0 0
0 1 0 0 0
0 1 0 1 1
0 0 1 1 0
Gives you the following scatter plot:

What about this :
A=[3 0 0; 0 2 0; 0 0 1];
imagesc(A)

Related

How to get all possible permutation matrices of a matrix

I need to create all possible permutation matrices for a matrix where every permutation matrix contains only one 1 in each column and each row, and 0 in all other places.
For example, below example in (1) is all possible permutation matrices for 2x2 matrix and in (2) is a all possible permutation matrices for 3x3 matrix and so on
So how can I get these matrices of a matrix NxN in MATLAB and store them into one three-dimensional matrix?
Here's my solution, using implicit expansion (tested with Octave 5.2.0 and MATLAB Online):
n = 3;
% Get all permutations of length n
p = perms(1:n);
% Number of permutations
n_p = size(p, 1);
% Set up indices, where to set elements to 1
p = p + (0:n:n^2-1) + (0:n^2:n^2*n_p-1).';
% Set up indices, where to set elements to 1 (for MATLAB R2016a and before)
%p = bsxfun(#plus, bsxfun(#plus, p, (0:n:n^2-1)), (0:n^2:n^2*n_p-1).');
% Initialize 3-dimensional matrix
a = zeros(n, n, n_p);
% Set proper elements to 1
a(p) = 1
The output for n = 3:
a =
ans(:,:,1) =
0 0 1
0 1 0
1 0 0
ans(:,:,2) =
0 1 0
0 0 1
1 0 0
ans(:,:,3) =
0 0 1
1 0 0
0 1 0
ans(:,:,4) =
0 1 0
1 0 0
0 0 1
ans(:,:,5) =
1 0 0
0 0 1
0 1 0
ans(:,:,6) =
1 0 0
0 1 0
0 0 1
Using repelem, perms and reshape:
n = 3; % matrix size
f = factorial(n); % number of permutation
rep = repelem(eye(n),1,1,f) % repeat n! time the diagonal matrix
res = reshape(rep(:,perms(1:n).'),n,n,f) % indexing and reshaping
Where res is:
res =
ans(:,:,1) =
0 0 1
0 1 0
1 0 0
ans(:,:,2) =
0 1 0
0 0 1
1 0 0
ans(:,:,3) =
0 0 1
1 0 0
0 1 0
ans(:,:,4) =
0 1 0
1 0 0
0 0 1
ans(:,:,5) =
1 0 0
0 0 1
0 1 0
ans(:,:,6) =
1 0 0
0 1 0
0 0 1
And according to your comment:
What I need to do is to multiply a matrix i.e Z with all possible
permutation matrices and choose that permutation matrix which
resulting a tr(Y) minimum; where Y is the results of multiplication of
Z with the permutation matrix. I Think I don't need to generate all
permutation matrices and store them in such variable, I can generate
them one by one and get the result of multiplication. Is that possible
?
You're trying to solve the assignment problem, you can use the well known hungarian algorithm to solve this task in polynomial time. No needs to generate a googleplex of permutation matrix.

randomly select histogram data MATLAB

I have an input 2D histogram that I want to do 2-fold cross-validation with. The problem is I don't know how to extract two mutually exclusive random samples of the data from a histogram. If it was a couple of lists of the positional information of each data point, that would be easy - shuffle the data in the lists in the same way, and split the lists equally.
So for a list I would do this:
list1 = [1,2,3,3,5,6,1];
list2 = [1,3,6,6,5,2,1];
idx = randperm(length(list1)); % ie. idx = [4 3 1 5 6 2 7]
shlist1 = list1(idx); % shlist1 = [3,3,1,5,6,2,1]
shlist2 = list2(idx); % shlist2 = [6,6,1,5,2,3,1]
slist1 = shlist1(1:3); % slist1 = [3,3,1]
elist1 = shlist1(4:6); % elist1 = [5,6,2,1]
slist2 = shlist2(1:3); % slist2 = [6,6,1]
elist2 = shlist2(4:6); % elist2 = [5,2,3,1]
But if this same data was presented to me as a histogram
hist = [2 0 0 0 0 0]
[0 0 0 0 0 1]
[0 1 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 1 0]
[0 0 2 0 0 0]
I want the result to be something like this
hist1 = [0 0 0 0 0 0]
[0 0 0 0 0 1]
[0 1 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 1 0 0 0]
hist2 = [2 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 1 0]
[0 0 1 0 0 0]
so that different halves of the data are randomly, and equally assigned to two new histograms.
Would this be equivalent to taking a random integer height of each bin hist(i,j), and adding that to the equivalent bin in hist1(i,j), and the difference to hist2(i,j)?
% hist as shown above
hist1 = zeros(6);
hist2 = zeros(6);
for i = 1:length(hist(:,1))*length(hist(1,:))
randNum = rand;
hist1(i) = round(hist(i)*randNum);
hist2(i) = hist(i) - hist1(i);
end
And if that is equivalent, is there a better way/built-in way of doing it?
My actual histogram is 300x300 bins, and contains about 6,000,000 data points, and it needs to be fast.
Thanks for any help :)
EDIT:
The suggested bit of code I made is not equivalent to taking a random sample of positional points from a list, as it does not maintain the overall probability density function of the data.
Halving the histograms should be fine for my 6,000,000 points, but I was hoping for a method that would still work for few points.
You can use rand or randi to generate two histograms. The first method is more efficient however the second is more random.
h = [[2 0 0 0 0 0]
[0 0 0 0 0 1]
[0 1 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 1 0]
[0 0 2 0 0 0]];
%using rand
h1 = round(rand(size(h)).*h);
h2 = h - h1;
%using randi
h1 = zeros(size(h));
for k = 1:numel(h)
h1(k) = randi([0 h(k)]);
end
h2 = h - h1;
Suppose H is your 2D histogram. The following code extracts a single random index with a probability proportional to the count at that index - which I think is what you want.
cc = cumsum(H(:));
if cc(1) ~= 0
cc = [0; cc];
end
m = cc(end);
ix = find(cc > m*rand, 1);
To extract multiple samples, you need to write your own find function (preferably a binary search for efficiency) that extracts some n number of samples in one call. This will give you a vector of indices (call it ix_vec) chosen with probability proportional to the Histogram count at each index.
Then if we denote by X the numerical values corresponding to each location in the Histogram, your random sample is:
R1 = X(ix_vec);
Repeat for the second random sample set.

Convert a column vector with values in {1,...,K} to a K-column matrix with a 1 in the appropriate column

Say I have a vector y like
2
4
3
10
and I want to obtain a matrix like
0 1 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1
What's the simplest/cleanest/"best" way of doing this in octave/matlab? I came up with:
repmat(y, 1, 10) == repmat(1:10, 4, 1)
Anyone have a better approach than this? It makes sense to me after having thought about it but I feel like it's a bit hard to parse for someone reading the code (though idk, I'm relatively new to vectorization, and a lot of vectorized code feels like that to me).
If you want your result to be sparse you can simply
n = numel( y ); % number of rows in resulting matrix
k = max(y(:)); % if you do not know k (num of columns) in advance
U = sparse( 1:n, y, 1, n, k );
If you want your result to be a full matrix
U = zeros( n, k );
U( sub2ind([n k], 1:n, y ) ) = 1;

In matlab, how to convert a list of points to a binary matrix

How would a list of points be converted to a binary matrix? Hopefully the operation will perform suitably for 640x640 images. Here is an example:
% the points
p = [2 2;2 3;3 3]
% the images is 4x4
img=zeros(4,4)
% set img to 1 for all points in p
??? this is the question?
% resulting binary image
img =
0 0 0 0
0 1 0 0
0 1 1 0
0 0 0 0
What about this:
linearInd = sub2ind(size(img), p(:,2), p(:,1));
img(linearInd) = 1;
You can simply do:
img(sub2ind(size(img), p(:,2), p(:,1))) = 1;
For example:
p = [2 2;2 3;3 3];
img = zeros(4,4);
img(sub2ind(size(img), p(:,2), p(:,1))) = 1
This would give you:
img =
0 0 0 0
0 1 0 0
0 1 1 0
0 0 0 0

How to calculate the centroid of a matrix?

I have the following 5x5 Matrix A:
1 0 0 0 0
1 1 1 0 0
1 0 1 0 1
0 0 1 1 1
0 0 0 0 1
I am trying to find the centroid in MATLAB so I can find the scatter matrix with:
Scatter = A*Centroid*A'
If you by centroid mean the "center of mass" for the matrix, you need to account for the placement each '1' has in your matrix. I have done this below by using the meshgrid function:
M =[ 1 0 0 0 0;
1 1 1 0 0;
1 0 1 0 1;
0 0 1 1 1;
0 0 0 0 1];
[rows cols] = size(M);
y = 1:rows;
x = 1:cols;
[X Y] = meshgrid(x,y);
cY = mean(Y(M==1))
cX = mean(X(M==1))
Produces cX=3 and cY=3;
For
M = [1 0 0;
0 0 0;
0 0 1];
the result is cX=2;cY=2, as expected.
The centroid is simply the mean average computed separately for each dimension.
To find the centroid of each of the rows of your matrix A, you can call the mean function:
centroid = mean(A);
The above call to mean operates on rows by default. If you want to get the centroid of the columns of A, then you need to call mean as follows:
centroid = mean(A, 2);