Matlab replacing 0 with empty cell in Cell array - arrays

I have a 10,000 x 65 Cell with 0's and 1's so for example if I type
C(1,1) I get [0] returned or likewise C(3,4) a [1] is returned
I need a way to turn every 0 into a blank cell and every 1 into a char t
I've tried the following with little success
[rows, cols] = size(M);
for i = 1:rows
for j = 1:cols
if strcmp(M(i,j), 1)
M(i,j) = 't';
end
end
end
It returns the same thing, I'm guessing its not recognising the 1's as strings. Any idea sort of simply doing the conversion straight in Excel.
thanks

You are not accessing the cell data-structure correctly.
First of all, if M really is a cell array, you will have to use M{i,j} to access the data.
What M(i,j)does is just create a sub-cell-array, which contains M{i,j} as entry.
Also strcmp isn't used correctly, if your cell array contains strings you should use strcmp(M{i,j}, '1').
If your cell array on the other hand contains integers, you would have to use: M{i,j}==1.

Related

Subscripted assignment dimension mismatch when combining corresponding array and cell array values in matlab

I have an array and a cell array with the same dimensions: A is a 1x2492 double array, and B is an 1x2492 cell cell array. I want to make a new cell array that assigns the values in A to the corresponding column values of B. Here was my code:
for n = 1:numel(B)
newArray(n) = [A(n),B{n}(2)];
newCellArray{n} = newArray;
end
When I ran the code, I got the error 'Subscripted assignment dimension mismatch.'
I think it's because some cells in B have multiple columns, and the code loop doesn't recognize that I want to assign the same value of A to all values in the cell.
For example, if cell 1 of B contains:
2 2355
23 1293
37 1222
I would like my code loop to assign the corresponding first value of A to 2355, 1293, and 1222. So basically, I'd like to have a new cell like this:
1 2355
1 1293
1 1222
I realize that this is a very confusing explanation, but I hope that it makes sense. Any and all help would be greatly appreciated - thank you very much!
I am not really sure what you are trying to do, but the code below will assign the value of A(ii) to every element in the first column of B{ii}. I am just saying this based on your example, but your explanation is really unclear..
C = B;
for ii=1:numel(C)
C{ii}(:,1)=A(ii);
end
And you are getting an error on newArray(n) = [A(n),B{n}(2)]; because you are trying to assign a vector to a singleton dimension. Try a(1) = [1 2] and you will still get an error, and this is independent on what your cell dimensions are, etc.. a(1,:)=[1 2], however, might work if the 2nd dimension of a is 2.
Try:
newCellArray = cell(numel(B),2);
for n = 1:numel(B)
lenB = length(B{n}(2));
newA = repmat(A(n),lenB);
newArray = [newA,B{n}(2)];
newCellArray = [newCellArray; newArray];
end

MATLAB: use strcmp(s1,s2) for variable length vector with strings

I have a query which I am trying to solve
I know that one can use strcmp(s1,s2) to compare two different strings to see whether they are the same. It gives 1 if that is the case.
However, how would one tackle this problem if you have a variable length array full of strings and you want to the whether all strings in the array are the same.
For example: ['NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'] we can see that all the strings are the same in this array. However, how would one go about with using strcmp(s1,s2).
Thanks guys!
If you want all pairwise comparisons between strings: call ndgrid to generate indices of all combinations, and then index into your cell array of strings and call strcmp:
x = {'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'};
[ii, jj] = ndgrid(1:numel(x));
result = strcmp(x(ii), x(jj));
In this case
result =
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
because all strings are the same.
You probably had a pairwise comparison using strcmp in mind, but you can use it directly on cell arrays:
x={'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'}
result=all(strcmpi(x{1},x(2:end)))
Compare the first element to the remaining elements. It returns true only if all elements are equal. For a pairwise comparison you could us:
[~,~,c]=unique(x);
result=bsxfun(#eq,c,c.')
If you're solving the problem with a matrix (i.e. every row is a string) there are no particularly nice solutions in my opinion, but if your strings are contained into a cell array, things are getting easier and nicer.
So we start by creating such cell array:
myStrings={'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'};
where each cell contains a string. This will make your code more robust as well since every string can have a different length (this is not true if you concatenate all your strings in a matrix).
Then you specify which string you want to find inside such cell array:
stringThatMustBeTested='NACA64A010';
Now you can use cellfun(), which is a function that applies another function to every cell of a given cell array as follows:
results=cellfun(#(x) strcmp(x,stringThatMustBeTested),myStrings);
Such line simply means "apply strcmp() to every generic cell x inside myStrings and compare the cell with stringThatMustBeTested".
Variable results will be a logical output in which element j will be true if the j-th cell in your cell array is equal to the string you want to test. If results is entirely composed by 1s (which you can check as if sum(results)==length(results)), then all the strings are the same in myStrings (given that stringThatMustBeTested is the unique string in your cell array but anyways, this solution can be extended to a broader string search inside a cell).

How do I reassign even and odd indices of a character array into a new smaller character array in Matlab?

In matlab I have a 32x1 character array A such that
A = {'F1' 'F2' 'F3' 'F4' 'F5' 'F6' ... 'F32'};
A = A';
Now I am trying to do the following with A.
For every even index of A meaning
A{2}, A{4}, A{6}...
I want to assign those values to a 16x1 character array B and for the odd indices of A I want to assign those values to a different 16x1 array C.
I use the following code:
for i=1:32
if mod(i,2)==0
B{i} = A{i};
else
C{i} = A{i};
end
end
and it works, but only partially because it assigns the right values at for e.g. B{2} and B{4} but the values in B{1} and B{3} are the same as in B{2} and B{4}.
Can anybody tell me how to reassign even and odd indices of a character array into a new smaller character array? My problem is that I am going from a 32x1 into a 16x1 and I'm not sure how to avoid the extra 16 entries.
Many thanks!
To get this question actual answered, use the idea of Luis Mendo in the comments. You can combine it with deal to save one line of code:
[B, C] = deal(A(2:2:end), A(1:2:end))
To make your loop work, you need a second running index jj:
A = {'F1' 'F2' 'F3' 'F4' 'F5' 'F6'};
for ii = 1:6
jj = ceil(ii/2);
if mod(ii,2)==0
B{jj} = A{ii};
else
C{jj} = A{ii};
end
end

How to use cell arrays in Matlab?

I am a beginner at using Matlab and came across cell arrays but I am not sure how to use indexing for it.
I have created a cell array of 5 rows and 3 cols by doing the following:
A = cell(5,3);
Now is it possible to go through the cell array by row first and then col like how a nested for loop for a normal array?
for i=1:5
for j=1:3
A{i,j} = {"random"} //random numbers/ string etc
end
end
With cell arrays you have two methods of indexing namely parenthesis (i.e. (...)) and braces (i.e. {...}).
Lets create a cell array to use for examples:
A = {3, 9, 'a';
'B', [2,4], 0};
Indexing using paranthesis returns a portion of the cell array AS A CELL ARRAY. For example
A(:,3)
returns a 2-by-1 cell array
ans =
'a'
0
Indexing using braces return the CONTENTS of that cell, for example
A{1,3}
returns a single character
ans =
a
You can use parenthesis to return a single cell as well but it will still be a cell. You can also use braces to return multiple cells but these return as comma separated lists, which is a bit more advanced.
When assigning to a cell, very similar concepts apply. If you're assigning using parenthesis, then you must assign a cell matrix of the appropriate size:
A(:,1) = {1,1}
if you assign a single value using parenthesis, then you must put it in a cell (i.e. A(1) = 2 will give you an error, so you must do A(1) = {2}). So it's better to use braces as then you are directly affecting the contents of the cell. So it is correct to go
A{1} = 2
this is equivalent to A(1) = {2}. Note that A{1} = {2}, which is what you've done, will not give a error but what is does is nests a cell within your cell which is unlikely what you were after.
Lastly, if you have an matrix inside one of your cells, then Matlab allows you to index directly into that matrix like so:
A{2,2}(1)
ans =
3
for example:
for i=1:5
for j=1:3
A{i,j} = rand(3)
end
end
should work perfectly fine
just skip the { } on the right side of the =

Concatenating 1D matrices of different sizes

I perhaps am going about this wrong, but I have data{1}, data{2}...data{i}. Within each, I have .type1, .type2.... .typeN. The arrays are different lengths, so horizontal concatenation does not work.
For simplicity sake
>> data{1}.type1
ans =
1
2
3
>> data{2}.type1
ans =
2
4
5
6
Results should be [1;2;3;2;4;5;6]
I've been trying to loop it but not sure how? I will have a variable number of files (a,b..). How do I go about looping and concatenating? Ultimately I need a 1xN array of all of this..
My working code, thanks..figured it out..
for i = 1:Types
currentType = nTypes{i}
allData.(currentType)=[];
for j = 1:nData
allData.(currentType) = [allData.(currentType); data{j}.(currentType)(:,3)]; %3rd column
end
end
Look at cat, the first argument is the dimension. In your simple example it would be:
result = cat(1,a,b);
Which is equivalent to:
result = [a;b];
Or you can concatenate them as row vectors and transpose back to a column vector:
result = [a',b']';
For the case of a structure inside a cell array I don't think there will be any way around looping. Let's say you have a cell array with M elements and N "types" as the structure fields for each element. You could do:
M=length(data);
newData=struct;
for i=1:M
for j=1:N
field=sprintf('type%d',j); % //field name
if (M==1), newData.(field)=[]; end % //if this is a new field, create it
newData.(field)=[newData.(field);data{i}.(field)];
end
end

Resources