remove cells that satisfy a specific condition - matlab

I have a cell array which each cell is an n-by-n matrix. I want to delete the cells for which inv(cell{i}'*cell{i}) gives warning that matrix is close to singular.
Thank you

In general, removing elements is the easy part. If C is your array, removing cells specified by the indices in vector idx can be done by:
C(idx) = {};
Regarding your specific problem, to check if a matrix is "almost" singular or not can be done with rcond (if the result is close to zero, it's probably singular). To apply it to all cells you can use cellfun in the following way:
idx = cellfun(#(x)(rcond(x' * x) < 1e-12), C);
Adjust the threshold value to your liking. The resulting idx is a logical array with 1s at the location of singular matrices. Use idx to remove these elements from C as shown above.

Create a function that check for your condition:
function state = CheckElement(element)
if ([condition])
state = 1;
else
state = 0;
end
end
then do cellfun on all you cell array elements like the following:
indices = cellfun(#CheckElement,myCellArray);
cellArray(indices ) = [];

Assuming you have already defined a issingular function defined you can use cellfun to get the indices of the cells that contain the matrices you want to remove.
c; % cell arry
singularIdx = cellfun((#x) issingular( inv(x' * x)), c); %' added single quote for SO syntax
cFiltered = c(~singluarIdx);
You'll probably need to write your own function to check for singularity, for more information on that see this question: Fast method to check if a Matrix is singular? (non-invertible, det = 0)

Related

find returns empty matrix

I have two vectors which are of length 200,000 approximately. They consist of dates in the datenum format.
%datenums
date_exp = datenum(data_exp(:,1:6));
date_sim = datenum(data_sim(:,1:6));
I want to find the dates in date_exp that exists in date_sim.
Then remove the values from date_exp
I have used the the ismember tool but ending up at i=38 find retunrs: Improper assignment with rectangular empty matrix.
Error in filter (line 18)
c(i)= find(ismember(date_sim(:),date_exp(i)),1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
c = zeros(length(date_sim),1);
for i=1:length(date_sim)
c(i)= find(ismember(date_sim(:),date_exp(i)),1);
if isempty(c(i)) == 1
c(i) = 0;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
I would be really helpful if anyone could help me out here.
The issue is because date_exp(38) must not be within date_sim. When there are no 1's in the input, find returns an empty array ([]).
Your code does not handle this as you would expect though because of this line.
c(i) = find(...)
In this case, if there are no matches (find() == []), then you are essentially calling
c(i) = [];
This deletes the ith element of c element
Therefore the following line is never true!
if isempty(c(i)) == 1
Instead, you should probably do something to handle the empty value.
index = find(ismember(date_sim(:), date_exp(i)), 1);
%// Only assign the index if it isn't an empty array
if ~isempty(index)
c(i) = index;
end
You don't have to worry about assigning zeros because your initial matrix is already full of zeros.
A Better Option
All of that aside, it would likely be a much better approach to not loop at all and to instead use the second output of ismember (on the arrays before you pass them to datenum) to give you the same result in a much more efficient way.
[~, c] = ismember(date_exp(:,1:6), date_sim(:,1:6), 'rows');

Matlab Matrix one-to-one correspondence index

I have a small code below for one-to-one correspondence index of the img matrix
for k = 1:length(I)
img(I(k),J(k)) = 0;
end
Now, I hope to get rid of for loop, but I cannot find proper matlab syntax to realize it.
img(I(1:length(I)), J(1:length(I)),1:3) = 0;
is not one-to-one correspondence index. Any help to realize the same function is appreciated.
Indexing in a linear fashion along multiple dimensions can be done using the sub2ind function:
img(sub2ind(size(img), I, J(1:length(I))) = 0;
You can also use sparse to get this done:
ind = sparse(I, J, 1, size(img,1), size(img,2)) == 1;
img(ind) = 0;
The first line of code generates a sparse matrix where the row values stored in I and the column values stored in J set the matrix values to 1, and we ensure that this is the same size as your image. We also convert to a logical array by equating the statement with 1. When you're done, simply use the result to index into your actual array and set the values to 0.
If you have a multi-channel matrix, you can do this temporally by making a call to repmat:
img(repmat(ind, [1 1 size(img,3)])) = 0;

In an assignment A(:) = B, the number of elements in A and B must be the same

if (hidden_layer>1)
for i =1 :hidden_layer
start_hidden_layer(i) = rand([gk(i+1),(gk(i)+1)])-0.5 ;
end
end
hi Friends.
I know every iteration was changed start_hidden_layer matrix dimensional.But all start_hidden_layer values must saved. How to solve this problem?
firstly hidden_layer>1
gk(i) is integer value for example 5 , 3, 8
Since you're calling rand with different matrix sizes on each iteration, you cannot save the results into a normal matrix. You need to use a cell matrix to store the result, like this:
%//preallocate the cell array
start_hidden_layer = cell(1, hidden_layer);
for i = 1:hidden_layer
start_hidden_layer{i} = rand([gk(i+1), (gk(i)+1)]) - 0.5;
end
For more on cell arrays and how to use them, see this Mathworks help doc.

How to find indices of the largest N elements in a cell?

I Matlab, I know that I can use this to get the largest number of a cell.
cell_max = cellfun(#(x) max(x(:)), the_cell);
However, there are two problems with this. First, I need the index of the maximum values as well. Second, I need not the single largest value of each cell, but its N largest values.
Is this possible with cells in Matlab?
Update: I have a pixel matrix that I get by running a filter on some input image file. From that matrix, I then split this matrix into tiles and want to keep only the N largest values per tile, while all other entries should be set to zero. (So I don't need the indices in the end, but they would allow me to create a new empty cell and copy over the large values.)
Tiles = mat2tiles(FilterResult, tileSize, tileSize);
If there is an easier way for my use case then using the mat2tiles script, I'd be grateful to know.
The routine cellfun can return the multiple arguments of the function you're passing in (see the documentation). So, assuming each cell contains a numeric vector of values, you can obtain the N largest elements of each cell like this:
% Using random data for the_cell
the_cell{1, 1} = rand(1, 12);
the_cell{1, 2} = rand(1, 42);
the_cell{2, 1} = rand(1, 18);
the_cell{2, 2} = rand(1, 67);
% First sort elements in each cell in descending order and keep indices
[s, i] = cellfun(#(x)sort(x(:), 'descend'), the_cell, 'UniformOutput', false);
% Then, in each resulting `s` and `i` cell arrays,
% take only the `N` first elements and indices
N = 4;
NLargestValues = cellfun(#(x)x(1:N), s, 'UniformOutput', false);
NLargestIndices = cellfun(#(x)x(1:N), i, 'UniformOutput', false);
NB: UniformOutput is set to false because outputs are not scalar.
Update
From your updates and comments we had, you can put all operations in some tileOperations function:
% Operation to perform for each tile in the_cell array
function [tile] = tileOperations(tile, N)
%[
% Return unique sorted values of the tile
v = unique(tile(:));
% Find threshold index
i = length(v) - N;
if (i <= 1), return; end % Quick exit if not enough elements
% Set elements below threshold to zero
threshold = v(i);
tile(tile < threshold) = 0.0;
%]
end
You can then call cellfun only once to repetitively apply operations on all tiles in the_cell:
filteredTiles = cellfun(#(x)tileOperations(x), the_cell, 'UniformOutput', false);

expand matrix in matlab?

I would like to expand matrix row by row under a conditional statement without initializing the matrix. In C++, simply I use std::vector and push_back method without initializing the size of the vector in C++. However, I want to do same scenario in Matlab. This is my pseudo code
for i = 1:lengt(data)
if ( condition )
K = [data(1) data(2) i]
end
K
Let us assume some working code to resemble your pseudo-code.
%// Original code
for i = 1:10
if rand(1)>0.5
data1 = rand(2,1)
K = [data1(1) data1(2) i]
end
end
Changes for "pushing data without initialization/pre-allocation":
To save data at each iteration we keeping on "stacking" data along a chosen dimension. This could be thought of as pushing data. For a 2D case, use either a "row vector push" or a "column vector push". For this case we are assuming a former case.
We don't index into K using the original iterator, but use a custom one,
that only increments when the condition is satisfied.
The code below must make it clear.
%// Modified code
count = 1; %// Custom iterator; initialize it for the iteration when condition would be satisfied for the first time
for i = 1:10
if rand(1)>0.5
data1 = rand(2,1)
K(count,:) = [data1(1) data1(2) i] %// Row indexing to save data at each iteration
count = count +1; %// We need to manually increment our custom iterator
end
end
If we assume from the above that data is an Nx2 matrix, and that you only want to save the rows that satisfy some condition, then you almost have the correct code to update your K matrix without having to initialize it to some size:
K = []; % initialize to an empty matrix
for i=1:size(data,1) % iterate over the rows of data
if (condition)
% condition is satisfied so update K
K = [K ; data(i,:) i];
end
end
K % contains all rows of data and the row number (i) that satisfied condition
Note that to get all elements from a row, we use the colon to say get all column elements from row i.