confused about the output of hist - matlab

I am confused by the
[m,n]=hist(y,x)
such as
M = [1, 2, 3;
4, 5, 6;
1, 2, 3];
[m,n] = hist(M,1:3)
Which results in
m = 2 0 0
0 2 0
1 1 3
Can someone please explain how m is calculated?

hist actually takes vectors as input arguments, you wrote a matrix, so it just handles your input as if it was several vector-inputs. The output are the number of elements for each container (in your case 1:3, the second argument).
[m,n] = hist([1,2,3;4,5,6;1,2,3],1:3)
treats each column as one input. You put in 3 inputs (# of columns) and you get 3 outputs.
[2 0 1]'
means, for the input [1;4;1] and the bin 1:3 two elements are in bin 1 and one element is in bin 3.
Look at the last column of m, here all three values are in the third bin, which makes sense, since the corresponding vector is [3;6;3], and out of those numbers all have to go into the bin/container 3.

Related

Using vector as indices not working as expected, matlab

Given a nXm matrix A and a mX2 matrix B and a matrix C of size mX1 containing 1s and 2s C=[1 2 1 2 1...], depending on which column, I want every row of A to be multiplied with. How can this be done? Or equivalently, given D = A*B how can I access only the values dictated by C. I tried D(:,C), but the result is not the expected.
Example a =[1 2; 3 4; 5 6] . c = [1 2 1] . a(?) = [1 4 5]
Any idea?
%example data
n=10;m=20;
A=rand(n,m)
B=rand(m,2)
C=round(rand(m,1))+1;
%solution:
B2=B(:,1); %multiplication vector
B2(C==2)=B(C==2,2) %change the ones where C==2
A*B2
You can run the following command for the last example:
a(sub2ind([3,2],1:3,c))'
In general case you can do like the following:
% n is the length of the D which is nx2 matrix
D(sub2ind([n,2],1:n,C))'

Eliminating zeros in a matrix - Matlab

Hi I have the following matrix:
A= 1 2 3;
0 4 0;
1 0 9
I want matrix A to be:
A= 1 2 3;
1 4 9
PS - semicolon represents the end of each column and new column starts.
How can I do that in Matlab 2014a? Any help?
Thanks
The problem you run into with your problem statement is the fact that you don't know the shape of the "squeezed" matrix ahead of time - and in particular, you cannot know whether the number of nonzero elements is a multiple of either the rows or columns of the original matrix.
As was pointed out, there is a simple function, nonzeros, that returns the nonzero elements of the input, ordered by columns. In your case,
A = [1 2 3;
0 4 0;
1 0 9];
B = nonzeros(A)
produces
1
1
2
4
3
9
What you wanted was
1 2 3
1 4 9
which happens to be what you get when you "squeeze out" the zeros by column. This would be obtained (when the number of zeros in each column is the same) with
reshape(B, 2, 3);
I think it would be better to assume that the number of elements may not be the same in each column - then you need to create a sparse array. That is actually very easy:
S = sparse(A);
The resulting object S is a sparse array - that is, it contains only the non-zero elements. It is very efficient (both for storage and computation) when lots of elements are zero: once more than 1/3 of the elements are nonzero it quickly becomes slower / bigger. But it has the advantage of maintaining the shape of your matrix regardless of the distribution of zeros.
A more robust solution would have to check the number of nonzero elements in each column and decide what the shape of the final matrix will be:
cc = sum(A~=0);
will count the number of nonzero elements in each column of the matrix.
nmin = min(cc);
nmax = max(cc);
finds the smallest and largest number of nonzero elements in any column
[i j s] = find(A); % the i, j coordinates and value of nonzero elements of A
nc = size(A, 2); % number of columns
B = zeros(nmax, nc);
for k = 1:nc
B(1:cc(k), k) = s(j == k);
end
Now B has all the nonzero elements: for columns with fewer nonzero elements, there will be zero padding at the end. Finally you can decide if / how much you want to trim your matrix B - if you want to have no zeros at all, you will need to trim some values from the longer columns. For example:
B = B(1:nmin, :);
Simple solution:
A = [1 2 3;0 4 0;1 0 9]
A =
1 2 3
0 4 0
1 0 9
A(A==0) = [];
A =
1 1 2 4 3 9
reshape(A,2,3)
ans =
1 2 3
1 4 9
It's very simple though and might be slow. Do you need to perform this operation on very large/many matrices?
From your question it's not clear what you want (how to arrange the non-zero values, specially if the number of zeros in each column is not the same). Maybe this:
A = reshape(nonzeros(A),[],size(A,2));
Matlab's logical indexing is extremely powerful. The best way to do this is create a logical array:
>> lZeros = A==0
then use this logical array to index into A and delete these zeros
>> A(lZeros) = []
Finally, reshape the array to your desired size using the built in reshape command
>> A = reshape(A, 2, 3)

How can I create systematic matrices in MATLAB?

I'm setting up a script and I want it to systematically go through ALL POSSIBLE 2x2, 3x3, and 4x4 matrices modulo 2, 3, 4, 5, 6, and 7. For example, for modulus 2 in a 2x2, there would be 16 possibilities (4^2 because there are 4 positions with 2 possibilities each). I'm having trouble getting MATLAB to not only form all these possibilities but to put them through my script one at a time. Any thoughts?
Thanks!
This solution uses allcomb from matlab file exchange.
%size
n=2
%maximum value
m=2
%generate input for allcomb
e=cell(1,n^2)
e(1:end)={[0:m-1]}
%generate all combinations.
F=reshape(allcomb(e{:}),[],n,n)
F is a 3D-Matrix, to get the first possibility use:
squeeze(F(1,:,:))
A slight generalization of this Q&A does the job in one line:
r = 2; %// number of rows
c = 2; %// number of columns
n = 2; %// considered values: 0, 1, ..., n-1
M = reshape(dec2base(0:n^(r*c)-1, n).' - '0', r,c,[]);
Result for r, c, n as above:
M(:,:,1) =
0 0
0 0
M(:,:,2) =
0 0
0 1
...
M(:,:,16) =
1 1
1 1

compare multiple matrices matlab

I have multiple matrices of the same size and want to compare them.
As a result I need a matrix which gives me the biggest of the 3 for every value.
I will clarify what i mean with an example:
I have 3 matrices with data of 3 persons.
I would like to compare these 3 and get a matrix as result.
In that matrix every cell/value should be the name of the matrix who had the highest value for that cell. So if in the 3 matrices the first value (1 colum, 1 row) is accordingly 2, 5, 8 the first value of the result matrix should be 3 (or the name of the 3 matrix).
If the three matrices are A, B, C, do this:
[~, M] = max(cat(3,A,B,C),[],3);
It creates a 3D "matrix" and maximizes across the third dimension.
Concatenate them on the 3rd dimension, and the use the SECOND output from max to get exactly what you want
A = rand(3,3);
B = rand(3,3);
C = rand(3,3);
D = cat(3, A, B, C)
[~, Solution] = max(D, [], 3)
e.g.:
D =
ans(:,:,1) =
0.70101 0.31706 0.83874
0.89421 0.33783 0.55681
0.68520 0.11697 0.45631
ans(:,:,2) =
0.268715 0.213200 0.124450
0.869847 0.999649 0.153353
0.345447 0.023523 0.338099
ans(:,:,3) =
0.216665 0.297900 0.604734
0.103340 0.767206 0.660668
0.127052 0.430861 0.021584
Solution =
1 1 1
1 2 3
1 3 1
edit
As I did not know about the second argument of the max-function, here is what you should NOT use:
old
Well, quick&dirty:
x=[2 5 8];
w=max(x)
[~,loc] = ismember(w,x)

Creating matrix from two vectors of (duplicated) indices in MATLAB

Suppose now I have two vectors of same length:
A = [1 2 2 1];
B = [2 1 2 2];
I would like to create a matrix C whose dim=m*n, m=max(A), n=max(B).
C = zeros(m,n);
for i = 1:length(A)
u = A(i);
v = B(i);
C(u,v)=C(u,v)+1;
end
and get
C =[0 2;
1 1]
More precisely, we treat the according indices in A and B as rows and columns in C, and C(u,v) is the number of elements in {k | A(i)=u and B(i)=v, i = 1,2,...,length(A)}
Is there a faster way to do that?
Yes. Use sparse. It assembles (i.e., sums up) the matrix values for repeating row-column pairs for you. You need an additional vector with the values that will be assembled into the matrix entries. If you use ones(size(A)), you will have exactly what you need - counting of repeated row-column pairs
spA=sparse(A, B, ones(size(A)));
full(spA)
ans =
0 2
1 1
The same can be obtained by simply passing scalar 1 to sparse function instead of a vector of values.
For matrices that have a large number of zero entries this is absolutely crucial that you use sparse storage. Another function you could use is accumarray. It can essentially do the same thing, but also works on dense matrix structure:
AA=accumarray([A;B]', 1);
AA =
0 2
1 1
You can pass size argument to accumarray if you want to create a matrix of specific size
AA=accumarray([A;B]', 1, [2 3]);
AA =
0 2 0
1 1 0
Note that you can actually also make it produce sparse matrices, and use a different operator in assembly (i.e., not necessarily a sum)
AA=accumarray([A;B]', 1, [2 3], #sum, 0, true)
will produce a sparse matrix (last parameter set to true) using sum for assembly and 0 as a fill value, i.e. a value which is used in cases a given row-column pair does not exist in A/B.