I have a sparse matrix:
B = sps.csc_matrix( (z , (row,column) )), shape = (N_x,N_y),dtype=int)
I would like to count the occurrences of the integer 2 column-wise.
However, B == 2 does not give a boolean sparse matrix.
Any ideas on how to do this?
Thanks!
Related
How to find the approximate numbers in two matrix?
For example,
There are two matrixes
A=[1.567 1.679 1.366 ;
2.467 3.587 6.134 ;
3.497 5.877 9.465]
B=[3.134 5.100 7.555 ;
7.465 4.715 4.267 ;
2.347 4.111 4.503]
So in A matrix 2.467 is close to 2.347 in B matrix.
How can I find them by coding?
Create a meshgrid of all the values in A and all the values in B so we can compare them:
[Amesh,Bmesh] = meshgrid(A(:),B(:))
Now find the absolute value of the difference:
absdiff = abs(Amesh-Bmesh)
This is a matrix of the absolute difference between every value in A vs. every value in B. So the minimum value in this table is your closest match between a value in A and B. To programatically find that value:
[x,y] = find(absdiff == min(absdiff(:)))
x =
3
y =
2
This calculates the minimum value of that matrix, and then finds the x/y position of that value. In this case x is the index into matrix B and y is the index into matrix A.
>> A(y)
ans =
2.4670
>> B(x)
ans =
2.3470
I have a vector T of length n and m other vectors of the same length with 0 or 1 used as condition to select elements of T. The condition vectors are combined into a matrix I of size n x m.
Is there a one liner to extract a matrix M of values from Tsuch that the i-th column of M are those elements in T that are selected by the condition elements of the i-th column in I?
Example:
T = (1:10)'
I = mod(T,2) == 0
T(I)'
yields
2 4 6 8 10
However
I = mod(T,2:4) == 0
T(I)'
yields an error in the last statement. I see that the columns might select a different number of elements which results in vectors of different lengths (as in the example). However, even this example doesn't work:
I = zeros(10,2)
I(:,1) = mod(T,2)==0
I(:,2) = mod(T,2)==1
Is there any way to achieve the solution in a one liner?
The easiest way I can think of to do something like this is to take advantage of the element-wise multiplication operator .* with your matrix I. Take this as an example:
% these lines are just setup of your problem
m = 10;
n = 10;
T = [1:m]';
I = randi([0 1], m, n);
% 1 liner to create M
M = repmat(T, 1, n) .* I;
What this does is expand T to be the same size as I using repmat and then multiplies all the elements together using .*.
Here is a one linear solution
mat2cell(T(nonzeros(bsxfun(#times,I,(1:numel(T)).'))),sum(I))
First logical index should be converted to numeric index for it we multiply T by each column of I
idx = bsxfun(#times,I,(1:numel(T)).');
But that index contain zeros we should extract those values that correspond to 1s in matrix I:
idx = nonzeros(idx);
Then we extract repeated elements of T :
T2 = T(idx);
so we need to split T2 to 3 parts size of each part is equal to sum of elements of corresponding column of I and mat2cell is very helpful
result = mat2cell(T2,sum(I));
result
ans =
{
[1,1] =
2
4
6
8
10
[2,1] =
3
6
9
[3,1] =
4
8
}
One line solution using cellfun and mat2cell
nColumns = size(I,2); nRows = size(T,1); % Take the liberty of a line to write cleaner code
cellfun(#(i)T(i),mat2cell(I,nRows,ones(nColumns,1)),'uni',0)
What is going on:
#(i)T(i) % defines a function handle that takes a logical index and returns elements from T for those indexes
mat2cell(I,nRows,ones(nColumns,1)) % Split I such that every column is a cell
'uni',0 % Tell cellfun that the function returns non uniform output
I have a huge matrix MxN matrix, say, A=rand([M,N]); and an index vector with N integer values between 1 and M, say, RandomIndex = randi(M,[1,N]);.
Now I would like to generate a row vector with entries
result = [A(RandomIndex(1),1), A(RandomIndex(2),2), ..., A(RandomIndex(N),N)]
What would be an efficient way to do this? It should be a very cheap operation but all my implementations are slow. I don't think there is a notation in Matlab to do this directly, is there?
The fastest option so far is
indexFunction = #(r,c) A(r,c);
result = cell2mat(arrayfun(indexFunction,RandomIndex,1:N,'UniformOutput',false));
Is there a more efficient way?
Use sub2ind
A(sub2ind(size(A), RandomIndex, 1:N))
sub2ind will convert the row and column indices given by RandomIndex and 1:N to linear indices based on size(A) which you can then use to index A directly.
Another way to do this is to use RandomIndex and 1:N to return an NxN matrix and then take the diagonal of this with diag
diag(A(RandomIndex, 1:N)).'
Note: .' is used to convert the row vector returned by diag to a column vector.
M=10;N=50;
A=rand([M,N]);
RandomIndex = randi(M,[1,N]);
out = zeros(1,numel(RandomIndex));
for ii = 1:numel(RandomIndex)
out(ii)=A(RandomIndex(ii),ii);
end
Another approach would be to use sparse and logical indexing:
M = sparse(RandomIndex, 1:N, 1) == 1;
out = A(M);
The first line of code generates a logical matrix where there is only 1 true value set in each column. This is defined by each value of RandomIndex. We convert this to a logical matrix, then index into your matrix to obtain the final random vector.
Use your index directly.
M = 100;N=100;
A = rand(M,N);
% get a random index that can be as large as your matrix
% 10 rows by 1 column
idx = randi(numel(A), 10,1);
t = A(idx);
Sorry for asking such a simple and silly question, but Matlab is really too hard to use for me. My question is just how to find the position the minimal value of a three dimensional array in Matlab.
For example, suppose I define a three dimensional array
m=zeros(2,2,2);
m(1,2,2)=-2;
The minimal value of m should be -2, located at (1,2,2). I can find the minimal value by
m0=min(min(min(m)));
But when I find its position by using
[x y z]=find(m==m0);
Instead of returning x=1, y=2 and z=2, it returns x=1, y=4 and z=1.
I appreciate if anyone would answer this question!
You can use min to find the minimum index of m and then convert it to x, y and z coordinates. There is no need to use find also.
min can be used with multiple output arguments to return the index of the minimum element. Here, I also use : to return every element of m as a column vector.
>> m=zeros(2,2,2);
>> m(1,2,2)=-2;
>> m(:)
ans =
0
0
0
0
0
0
-2
0
>> [~, ind] = min(m(:))
ind =
7
Now we have our index we need to convert it back into x, y and z coordinates. This can be done using ind2sub or manually by hand.
>> [x y z] = ind2sub(size(m), ind)
x =
1
y =
2
z =
2
You're correct. This is more complicated than it should be. The problem is that MATLAB is hardwired to work with matrices (i.e. arrays of rank 2), rather than arrays of general rank. Here's the solution:
m0 = min(m(:))
[x y z] = ind2sub(size(m), find(m(:) == m0))
Explanation:
If you type help find, you may notice that your original code was using the [rows, cols, vals] version of find, which is not what you expected.
Instead, min(m(:)) is a simplification of your min(min(min(m))). It automatically reshapes m into a rank one array (i.e. a vector).
The expression find(m(:) == m0) returns a single index for the minimum position in this reshaped vector. Finally, ind2sub converts this single index into a set of three indices, given the shape of m.
I have a matrix A which is 21x1 and contains only ones and twos.
Then I have a matrix B which is 6 * 600 matrix of numbers ranging between 0 and 21.
I want to generate a matrix C which is 6 * 600 matrix containing ones and twos such that:
If B matrix has a zero, matrix C should have a zero on that place. If B matrix has number 5, then matrix C should have the element on row 5 of matrix A and so on and so forth.
Please let me know if this is not clear.
Let us generate some sample inputs:
A = randi(2,21,1);
B = randi(22,6,600)-1;
The output C will then be:
C = B*0; %// preallocation + take care of the elements that need to be 0
C(B>0) = A(B(B>0)); %// logical indexing
The explanation of the 2nd line is as follows:
RHS
B>0 - return a logical array the size of B which has the meaning of whether this specific element of B is larger-than-0 value.
B(B>0) - return the elements of B for which there are true values in B>0 (i.e. numbers that can be used to index into A).
A(...) - return the elements of A that correspond to the valid indices from B.
% Generate matrices fitting the description
A = round(rand(21,1))+1;
B = round(rand(6,600)*21);
C = zeros(6,600);
% Indexing impossible since zeroes cannot be used as index. So treat per element using linear indexing.
for ii = 1:(6*600)
if B(ii) == 0
C(ii) = 0;
else
C(ii) = A(B(ii));
end
end
Although the piece of code could be optimized further this is the most clear way of creating understanding and speed is not needed if it's only this small matrix evaluated a limited number of times.