Matlab Cell Array Data - arrays

I have a cell array it is 100x1, variable name is CellA. As you will see from the png file attached, the cell array contains various size matrices in each of the 100 different cells.
I want to extract that data. Actually, I am trying to find the number of unique elements in each cell and their frequency. Below is my code which gets dimensional errors:
for i=1:length(CellA)
if isempty(CellA{i})
continue;% do nothing
else
unqmz(i,:) = unique(CellA{i})';
countmz(i,:) = histc(CellA{i}, unqmz(i))';
end
Eventually, I want to plot count versus unique number for each different cell array where the total number of counts for that cell exceeds a pre-determined value. e.g.) 4

You can also do it this way:
unqmz = cellfun(#unique, CellA, 'uni', 0);
countmz = arrayfun(#(n) histc(CellA{n},unqmz{n}), 1:numel(CellA), 'uni', 0).';

See if this works out for you -
%// Get result data into unqmz and countmz
unqmz = cell(numel(CellA),1);
countmz = cell(numel(CellA),1);
for ii=1:numel(CellA)
if isempty(CellA{ii})
continue;% do nothing
else
unqmz(ii) = {unique(CellA{ii})'} %//'
countmz(ii) = {histc(CellA{ii}, cell2mat(unqmz(ii)))'} %//'
end
end
%// Count of number of unique numbers in each cell
count_uniqs = cellfun(#numel,unqmz);
%// Plot (assuming you want to plot everything in one figure window)
figure,
for k = 1:size(countmz,1)
if count_uniqs(k)>4
plot(cell2mat(unqmz(k)),cell2mat(countmz(k)),'x')
hold on
end
end

Related

matlab: logically comparing two cell arrays

I have an excel file from which I obtained two string arrays, Titles of dimension 6264x1 and another Names of dimension 45696x1. I want to create an output matrix of size 6264x45696 containing in the elements a 1 or 0, a 1 if Titles contains Names.
I think I want something along the lines of:
for (j in Names)
for (k in Titles)
if (Names[j] is in Titles[k])
write to excel
end
end
end
But I don't know what functions I should use to achieve what I have in the picture. Here is what I have come up with:
[~,Title] = xlsread('exp1.xlsx',1,'A3:A6266','basic');
[~,Name] = xlsread('exp1.xlsx',2,'B3:B45698','basic');
A = cellstr(Title);
GN = cellstr(Name);
BinaryMatrix = false(45696,6264);
for i=1:1:45696
for j=1:1:6264
if (~isempty(ismember(A,GN)))
BinaryMatrix(i,j)= true;
end
end
end
the problem with this code is that it never finishes running, although there are no suggestions within matlab.
You can use third output of unique to get numbers corresponding to each string element and use bsxfun to compare numbers.
GN = cellstr(Name);
A = cellstr(Title);
B = [ GN(:); A(:)];
[~,~,u]= unique(B);
BinaryaMatrix = bsxfun(#eq, u(1:numel(GN)),u(numel(GN)+1:end).');
ismember can handle cell arrays of character vectors. Its second output tells you the information you need, from which you can build the result using sparse (it could also be done by preallocating and using [sub2ind):
[~, m] = ismember(Titles, Names);
BinaryMatrix = full(sparse(nonzeros(m), find(m), true, numel(Names), numel(Titles)));

Store arrays in index in a nested for loop in matlab

I have 50 images, stored as arrays in a 1x50 cell index called AllImages. Basically I want to make a new index with arrays that contain elements in the same position of the 50 arrays.
I want to see how each pixel in the same spot of the 50 images changes in the 50 images.
Theoretically, I would get an index of arrays with 50 elements each, because I want the first element of each of the 50 arrays in its own array, the second element of each of the 50 arrays in its own array, so on and so forth.
So far, here is my code:
for m = 1:5000 % number of pixels per image
for n = 1:50 % for the 50 images, all the same size
pixels(n) = allImages{n}(m)
end
allpixels{m} = pixels
end
I end up getting a 1x50 cell index for allpixels, even though I want 5000. I'm not sure what I did wrong.
Is there an easier way to do this or fix the code? Thanks so much!
are the images of the same size?
in that case first change them to a matrix using cell2mat
[i,j] = size(allImages{1})
n = numel(allImages)
allImages = cell2mat(allImages);
allImages = reshape(allImages,[i,j,n]);
because now you can just select your pixel. for example:
pixel = squeeze(allImages(1,1,:))
To get them all in a new cell you could permute and reshape your matrix
allImages = permute(allImages ,[3 1 2]);
allImages = reshape(allImages ,[n,i*j]);
pixels = mat2cell(allImages,n,ones([1,i*j]));
But for most mathematical operations it is easier to just keep them as one matrix.
As two rules of thumb in matlab you want to use matrices as much as possible, and avoid for-loops.

Extracting data from a 3D cell array into a 2D Matrix - MATLAB

I have a cell array that is three dimensional i.e. 16x10x3 and I would like for all values in :,:,1 :,:,2 and :,:,3 to be extracted into a column of a matrix each.
I thought about pre-allocating a matrix and then just running a basic loop such as:
for m=1:3
mat(:,m) = ([a{:,:,m}]);
end
Is there a more efficient way of doing this without having to rely on a loop?
EDIT: There are different numbers of values between :,:,1/2/3.
It's high time you get into bsxfun! Here's the implementation -
%// Get the number of elements in each column of the input cell array
lens = sum(cellfun('length',reshape(a,[],size(a,3))),1)
%// Store the maximum number of elements possible in any column of output array
max_lens = max(lens)
%// Setup output array, with no. of rows as max number of elements in each column
%// and no. of columns would be same as the no. of columns in input cell array
mat = zeros(max_lens,numel(lens))
%// Create as mask that has ones to the "extent" of number of elements in
%// each column of the input cell array using the lengths
mask = bsxfun(#le,[1:max_lens]',lens) %//'
%// Finally, store the values from input cell array into masked positions
mat(mask) = [a{:}]

How to permute the arrays within a cell array without using loops

I have a two arrays within a <1x2 cell>. I want to permute those arrays. Of course, I could use a loop to permute each one, but is there any way to do that task at once, without using loops?
Example:
>> whos('M')
Name Size Bytes Class Attributes
M 1x2 9624 cell
>> permute(M,p_matrix)
This does not permute the contents of the two arrays within M.
I could use something like:
>> for k=1:size(M,2), M{k} = permute(M{k},p_matrix); end
but I'd prefer not to use loops.
Thanks.
This seems to work -
num_cells = numel(M) %// Number of cells in input cell array
size_cell = size(M{1}) %// Get sizes
%// Get size of the numeric array that will hold all of the data from the
%// input cell array with the second dimension representing the index of
%// each cell from the input cell array
size_num_arr = [size_cell(1) num_cells size_cell(2:end)]
%// Dimensions array for permuting with the numeric array holding all data
perm_dim = [1 3:numel(size_cell)+1 2]
%// Store data from input M into a vertically concatenated numeric array
num_array = vertcat(M{:})
%// Reshape and permute the numeric array such that the index to be used
%// for indexing data from different cells ends up as the final dimension
num_array = permute(reshape(num_array,size_num_arr),perm_dim)
num_array = permute(num_array,[p_matrix numel(size_cell)+1])
%// Save the numeric array as a cell array with each block from
%// thus obtained numeric array from its first to the second last dimension
%// forming each cell
size_num_arr2 = size(num_array)
size_num_arr2c = num2cell(size_num_arr2(1:end-1))
M = squeeze(mat2cell(num_array,size_num_arr2c{:},ones(1,num_cells)))
Some quick tests show that mat2cell would prove to be the bottleneck, so if you don't mind indexing into the intermediate numeric array variable num_array and use it's last dimension for an equivalent indexing into M, then this approach could be useful.
Now, another approach if you would like to preserve the cell format would be with arrayfun, assuming each cell of M to be a 4D numeric array -
M = arrayfun(#(x) num_array(:,:,:,:,x),1:N,'Uniform',0)
This seems to perform much better than with mat2cell in terms of performance.
Please note that arrayfun isn't a vectorized solution as most certainly it uses loops behind-the-scenes and seems like mat2cell is using for loops inside its source code, so please do keep all these issues in mind.

How to obtain a vector with the indexes of the elements given in a combination?

I have a vector that stores unique area values. I am using a for loop to generate an array with the sum of every possible combination of these areas, as shown below:
A_values=[155 143 193.5 233.25 419.7 351.9 256.8 1054.9 997.5 997.5 726.2 73.5 66.8 62 82.5]
comb_sums=[];
indexes=[];
for x=1:length(A_values)
comb_sums=[comb_sums;
sum(combntns(A_values,x),2)];
end
Now I would like to obtain the indexes of the elements given in every combination. For example, if some of the possible given combinations had been [143], [726.2 66.8] and [155 419.7 256.8], the code would give me an array like this:
indexes=[ 2 0 0 0;
11 13 0 0;
1 5 7 0];
The array that I get from the for loop is obviously much bigger than the example given in the indexes variable above, so indexes would give me a much bigger array too.
You can create an array of indices and use combntns on it, just you like did on A_values -
nA = numel(A_values)
for k1 = 1:nA
comb_out = combntns([1:nA],k1);
indexes = [comb_out zeros(size(comb_out,1),nA - size(comb_out,2))]
end
If you would like to store up indexes from each iteration into a huge array named indexes_all instead, you can pre-calculate the sizes of indexes for each iteration and use them to pre-allocate for indexes_all. The code would be -
%// Number of A_values to be used at various places in the code
nA = numel(A_values);
%// Get number of rows to be produced at each iteration
nrows = arrayfun(#(x) factorial(nA)/(factorial(x)*factorial(nA-x)),1:nA);
%// Preallocate with zeros as also needed in the desired output
indexes_all = zeros(sum(nrows),nA);
off1 = 1; %// row-offset
for k1 = 1:nA
comb_out = combntns(1:nA,k1); %// combntns on array of indices
indexes_all(off1:off1+nrows(k1)-1,1:size(comb_out,2)) = comb_out; %// Store
off1 = off1+nrows(k1); %// Update row-offset for next set of combinations
end

Resources