Cell array to matrix conversion in matlab - arrays

I would like to covert three <1xN cell> (A, B and C) into a single Nx3 matrix. Could someone help me with this?
C={{1xN}; {1xN}; {1xN}};
where each N is a number in single quotes, e.g.
C = {{'123123' ,'12324', ....N times}; {'123123', '12324', ....N times}; {'123123', '12324' ,....N times}}
Since a couple of them mentioned about the ridiculous input, this is the reason for having it in the above form.
The three nested array of cells are the results of a regexp where my string and expression are both strings. Therefore I have the output of regexp as three cell arrays of row vectors.
For e.g.
node_ids=regexp(nodes,'(?<=node id=")\d*','match');
I can use cat function and then use a str2double for all three cell arrays and finally form a matrix by cell2mat.
For e.g.
node_ids=cat(1,node_ids{:});node_ids=str2double(node_ids);
But this takes more time and has more LOC.
My question is can it be done with fewer lines of code?
I tried using the cat function but keep getting this error:
Cannot support cell arrays containing cell arrays or objects.

Your input data is pretty bad.... why are you using a nested array of cells where each element is a string?
In any case, assuming C is your original input data, do this:
C = {{'123123' '12324'}; {'123123' '12324'}; {'123123' '12324'}};
out = cellfun(#(x) cellfun(#str2num, x, 'uni', 0), C, 'uni', 0);
out = cell2mat(cellfun(#cell2mat, out, 'uni', 0));
First line is some dummy data. Next line first goes through every nested cell element over your cell array and converts the strings into numbers. However, these are still in cell arrays. As such, the next line converts each cell array in the nested cell into a matrix, then we merge all of the cells together into one final matrix.
We get:
>> out
out =
123123 12324
123123 12324
123123 12324

Related

MATLAB indexing all the cells in a cell array of matrices

I have a cell array where each cell contains a matrix (different sizes). I would like, e.g., to take all the second columns of the matrices providing a command like:
aux = cArray{:}(:,2)
The result I'd like to obtain is a cell array where each cell contains the second column of the original matrix, but the command doesn't work (and I can even see why, since the output of cArray{:} is not a matrix ... )
Is there a compact command to get what I want instead of a cycle filling up the cell array ?
The reason why it doesn't work is that indexing a cell array with {:} produces a comma-separated list, which is not indexable anymore. You can view it as the "unwrapped" contents of the cell array separated by commas.
You can achieve what you want with cellfun:
result = cellfun(#(x) x(:,2), cArray, 'uniformoutput', false);
This applies the anonymous function #(x) x(:,2) to each cell's contents, and packs the results in a cell array.

How to remove a row from a matrix inside a cell array

I have a cell array (A) with size of 400 x 1 and each cell of this array includes a matrix with size 9 x 4. As such, it looks like this:
A={[9x4 double];[9x4 double];...;[9x4 double]};
Now, I want to remove the zero rows from these sub matrices and then obtain a new A cell array called A_new where its sub matrices don't have any zero rows like this:
A_new={[5x4 double];[7x4 double];...;[4x4 double]};
By my below code, I can find the index of rows which are not zero but I couldn't create my cell array like I mentioned above. This is my written code and for the bold part, I have a problem and I couldn't solve it.
for i=1:A_Length
[row,col]=find(A{i,1});
out=[row col];
NNZ_row=unique(row);
Length_NNZ= length(NNZ_row);
for j=1:Length_NNZ
**A_NonZero{i,1}= ??????????**
end
end
What I would do is take each cell, then use all on the opposite of the matrix over all of the columns in each row to determine which rows contain all zeroes. Once you do this, use these locations and remove those rows from this matrix and save this to your new matrix.
As such, do this:
A_new = cell(1,numel(A));
for i=1:numel(A)
mat = A{i};
ind = all(~mat, 2);
A_new{i} = mat(~ind,:);
end
The first line of code creates a new cell array that is the same size as A. Next, for each element in A, extract the matrix at each cell location, use all on the opposite of this matrix to find those elements that we need to keep, then save this new matrix into the corresponding location in A_new.
If you want to do this in a single line of code, use cellfun:
A_new = cellfun(#(x) x(~all(~x,2),:), A, 'uni', 0);
The first argument to cellfun is an anonymous function that performs what the for loop was doing. We find those rows that contain all zeroes and use those to remove the rows in each matrix in the cell array. The second argument is the matrix we want to operate on, which is A. The 'uni' and 0 flags are important because the outputs are not single values but matrices, and so the output of this function will be a cell array that is the same size as A where each element is the matrix for those corresponding locations in A with the zero rows removed.
You should use a combination of cellfun and any:
A_new = cellfun(#(x) x(any(x~=0,2),:), A, 'UniformOutput', false);
should do the trick.

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.

Matlab, find common elements of two cell arrays

I have two cell arrays, the sizes are 1x20033 and 1x19. Let's call these two cell arrays as A and B. I want to compare each cell of A with each cell of B to see if there is any common element.
Finally, I need to build a binary matrix and put one when there is a match.
I tried this:
BinaryMatrix=zeros(20033,19);
for i=1:1:20033
for j=1:1:19
match=find(ismember(A{i},B{j}));
if match==1
BinaryMatrix(i,j)= 1;
end
end
end
but I faced this error: "Input A of class double and input B of class cell must be
cell arrays of strings, unless one is a string."
Please tell me What should I do to solve it?
The code that you have almost works. What I would recommend you do is split up the strings found in A and B by spaces. As such, A and B would then be cell arrays of elements where each element in A or B is a single word. The spaces will serve as delimiters for separating out the words.
Once you do this, use intersect to see if there are any common words between the words in A and the words in B. intersect works by considering two arrays (these can be numeric arrays, cell arrays, etc.) C and D as sets, and it returns the set intersection between these two arrays.
In our case, C and D would be a cell array of words separated by spaces from A and B. intersect(C,D) will return a cell array of strings where each element in the output is a string found in both C and D. As such, should this cell array be non-empty, we have found at least one common word between C and D. If this is the case, then set your binary flag at the location of your matrix to 1. In other words:
BinaryMatrix = false(20033,19);
for i=1:1:20033
for j=1:1:19
Asplit = strsplit(A{i});
Bsplit = strsplit(B{j});
if (~isempty(intersect(Asplit, Bsplit)))
BinaryMatrix(i,j)= true;
end
end
end
You'll notice that I have changed your matrix from zeros(20033,19), to false(20033,19). The reason why is because by doing zeros, you are allocating 8 bytes per number in your matrix as this will create your matrix in double precision. By doing false, this will be a logical matrix instead, and you are allocating 1 byte per number. Seeing as how you want BinaryMatrix to be either true or false, don't use double - use logical. I don't know how large both cell arrays are, and so doing this will cut down your memory consumption by 8.
Minor Note
strsplit is only available from R2013a and onwards. If you have a version of MATLAB that is R2012b and lower, replace strsplit with regexp. As such, you would replace the two lines in the for loop with:
Asplit = regexp(A{i}, ' ', 'split');
Bsplit = regexp(B{j}, ' ', 'split');

Binsearch in cell matrix in Matlab

I have a cell matrix with 2 rows - sorted cell array of different strings and array of numbers. Also I have an example string. It's guarantied that this string appears in the 1st row in the cell array. I want to get index of example's appearance in cell array of strings.
Is there any function in Matlab, that provides solving with logarithmic complexity (something like binary search)?
If you look at ismember code (type open ismember), you'll see that it basically
Checks if the array is sorted (by calling issorted);
If not, it sorts the array;
Then it applies binary search.
So you can directly use ismember.
Example:
>> strings = {'a', 'aa', 'be', 'day', 'yes'};
>> [tf, loc ] = ismember('day', strings);
>> loc
loc =
4
Or maybe modify ismember (save it with another name) to bypass step 1, since you already know your array is sorted.

Resources