Accessing the contents of a 1x1 matlab cell - matlab

I'm not sure about the terminology, but I have read data from a text file into a 1x1 cell array P. When examining P, it lists "<142x2 cell>" in the (1,1) position. From there I can double-click this and it opens up into the 142x2 cell that I actually want. The issue is, I don't get how to manipulate this data via code to convert from the 1x1 cell array to the 142x2 cell array.
Also, I cannot find anywhere what the curly brackets denote.

I don't get how to manipulate this data via code to convert from the 1x1 cell array to the 142x2 cell array.
The cell array P is actually a 1x1 cell array, which in turn contains another cell array 142x2. This type of output is very common when using textscan. To access the inner cell array, you can simply use curly braces ({}), like so:
Q = P{1}; // or P{:} if you're certain that P holds only one cell
The resulting Q should hold your 142x2 cell array. I usually "flatten" P by doing P = P{:}, without using an intermediate variable.
Also, I cannot find anywhere what the curly brackets denote.
Have you read MATLAB's documentation about special characters? Here's what it says:
Curly braces are used in cell array assignment statements. For example, A(2,1) = {[1 2 3; 4 5 6]}, or A{2,2} = ('str'). See help paren for more information about { }.
I would also urge you to read the following (very) related question: Difference between accessing cell elements using {} and () (curly braces vs. parentheses)

Short answer: You can assign the content of the first cell in P to P.
Example:
P = {cell(142,2)}; %Create a 142x2 cell inside a cell
P = P{1}; %Solution: Now P is a 142x2 cell
If you try help cell it will lead you to help paren that explains the use of curly brackets.

Related

Printing progress in command window

I'd like to use fprintf to show code execution progress in the command window.
I've got a N x 1 array of structures, let's call it myStructure. Each element has the fields name and data. I'd like to print the name side by side with the number of data points, like such:
name1 number1
name2 number2
name3 number3
name4 number4
...
I can use repmat N times along with fprintf. The problem with that is that all the numbers have to come in between the names in a cell array C.
fprintf(repmat('%s\t%d',N,1),C{:})
I can use cellfun to get the names and number of datapoints.
names = {myStucture.name};
numpoints = cellfun(#numel,{myStructure.data});
However I'm not sure how to get this into a cell array with alternating elements for C to make the fprintf work.
Is there a way to do this? Is there a better way to get fprintf to behave as I desire?
You're very close. What I would do is change your cellfun call so that the output is a cell array instead of a numeric array. Use the 'UniformOutput' flag and set this to 0 or false.
When you're done, make a new cell array where both the name cell array and the size cell array are stacked on top of each other. You can then call fprintf once.
% Save the names in a cell array
A = {myStructure.name};
% Save the sizes in another cell array
B = cellfun(#numel, {myStructure.data}, 'UniformOutput', 0);
% Create a master cell array where the first row are the names
% and the second row are the sizes
out = [A; B];
% Print out the elements side-by-side
fprintf('%s\t%d\n', out{:});
The trick with the third line of code is that when you unroll the cell array using {:}, this creates a comma-separated list unrolled in column-major format, and so doing out{:} actually gives you:
A{1}, B{1}, A{2}, B{2}, ..., A{n}, B{n}
... which provides the interleaving you need. Therefore, providing this order into fprintf coincides with the format specifiers that are specified and thus gives you what you need. That's why it's important to stack the cell arrays so that each column gives the information you need.
Minor Note
Of course one should never forget that one of the easiest ways to tackle your problem is to just use a simple for loop. Even though for loops are considered bad practice, their performance has come a long way throughout MATLAB's evolution.
Simply put, just do this:
for ii = 1 : numel(myStructure)
fprintf('%s\t%d\n', myStructure(ii).name, numel(myStructure(ii).data));
end
The above code is arguably more readable in comparison to what we did above with cell arrays. You're accessing the structure directly rather than having to create intermediate variables for the purpose of calling fprintf once.
Example Run
Here's an example of this running. Using the data shown below:
clear myStructure;
myStructure(1).name = 'hello';
myStructure(1).data = rand(5,1);
myStructure(2).name = 'hi';
myStructure(2).data = zeros(3,3);
myStructure(3).name = 'huh';
myStructure(3).data = ones(6,4);
I get the following output after running the printing code:
hello 5
hi 9
huh 24
We can see that the sizes are correct as the first element in the structure is simply a random 5 element vector, the second element is a 3 x 3 = 9 zeroes matrix while the last element is a 6 x 4 = 24 ones matrix.

Writing the output of variable length cells into a single column cell array in MATLAB

I am trying to write the output from a variable length cell array to a single column cell array.
Eg:
I have
A a;b
B c
C b;c
D a;b;d
E e;g;h
F a;b
as the input file. I want to read all the entries in the second column into separate cells in a row and store the output as the following:
a
b
c
b
c
a
b
d.... and so on.
I tried
for m=1:size(txt)
c(:,m)=strsplit(txt{m},';');
end
However, I am unable to write the output into a column and getting the following error:
Assignment has more non-singleton rhs dimensions than non-singleton subscripts
I understand that the dimensions of c should be more than that of size(txt) but I am not sure how to enter write the output from c into the first empty cell present in the column.
This is because you have declared c to be a matrix but you want it to be a single column. In addition, strsplit creates a cell array of results here each split string is placed in an element in the cell array. Also, this cell array is a row-wise cell array, meaning that you will get a cell array of dimensions 1 x N where N is the total number of strings resulting from the call the strsplit.
As such, what I would recommend you do is create a master cell array to store all of the strings as you iterate through each row, then concatenate and create one final cell array at the end.
Assuming the code you wrote up until this point is correct, do something like this:
c = cell(numel(txt), 1);
for m = 1 : numel(txt)
c{m} = strsplit(txt{m}, ';');
end
c = horzcat(c{:});
The first line creates a master cell array to store our string split characters per line of the text file. Next, for each line of the file, we split the string with the semicolon character as the delimiter and we place these split results into the right cell in the master array. Once this is finished, we use horzcat to place all of the characters into a single row of cells in the end. This creates a row of cell array elements though. Using horzcat is required as we are concatenating many row-wise cell arrays together into a single row. Trying to do this vertically will give you an error. Simply transpose the result if you want a column:
c = horzcat(c{:}).';

subindex into a cell array of strings

I have a 6 x 3 cell (called strat) where the first two columns contain text, the last column has either 1 or 2.
I want to take a subset of this cell array. Basically select only the rows where the last column has a 1 in it.
I tried the following,
ff = strat(strat(:, 3), 1:2) == 1;
The error message is,
Function 'subsindex' is not defined for values of class 'cell'.
How can I index into a cell array?
Cell arrays are accessed through braces {} instead of parentheses (). Then, as a 2nd subtlety, when pulling values out of a cell arrays, you need to gather them...for numerics you gather them into regular arrays using [] and for strings you gather them into a new cell array using {}. Confusing, eh?
ff = { strat{ [strat{:,3}]==1 , 1:2 } };
Gathering into cell arrays this way can often give the wrong shape when you're done. So, you might try something like this
ind = find([strat{:,3}]==1); %find the relevant indices
ff = {{strat{ind,1}; strat{ind,2}}'; %this will probably give you the right shape

Allow non-numeric entries in matrix in MATLAB

I wrote a code that replaces non-numeric values in the matrix by some number.
Now, to test it I would like to allow MATLAB to accept non-numeric entries.
My code starts with prompt:
matrix_input = input('Please enter the matrix: x=');
If I enter something like [1,2,3;4,5,?], MATLAB gives an error: Unbalanced or unexpected parenthesis or bracket. Since all brackets seem to be balanced, I assume this is due to non-numeric entry. Is it possible to make MATLAB allow non-numeric entries?
You need a cell array. Each cell of a cell array can hold any type of data. Curly braces are used to create a cell array like this:
cell_array = {1, 2, 3; '4', '?', 6};
If you use regular braces to access an element in a cell array you get a cell. If you use curly braces you get the contents of the cell. It's this difference that tends to catch people out with cell arrays.
cell_array(1) % Returns a 1x1 cell containing the value 1.
cell_array{1} % Returns 1
EDIT
Out of curiosity, what code are you using to replace the non-numeric values? For a cell array I came up wit the following:
idx = cellfun(#isnumeric, cell_array);
cell_array(~idx) = {NaN};
matrix = cell2mat(cell_array);
As mentioned in the comments, you could also use a struct array:
struct_array = struct('v', {1, 2, 3; '4', '?', 6});
This would create an array of structures where the field v contains the value. However, I can't think of a neat way to perform the replacement at the minute.

matlab: Adding square brackets to all individual numerical values within cell arrays

I wish to add a cell array (Ma) into another cell array. However both needs to be of the same format (individual cells in square brackets).
For instance I have an array..
Ma{1,:}.'
ans =
Columns 1 through 8
'83.6' '85.2' '91' '87.9' '91.8' '86.3' '90.6' '90.2'
How do i add square brackets to all the numerical values of very individual cells?
Below is what i wish to obtain, it is also a 1x8 cell.
ans =[83.6] [85.2] [91] [87.9] [91.8] [86.3] [90.6] [90.2]
Your cell values are strings (you can tell by the quote marks ' surrounding the values). You wish to convert them to numerical values ("add square brrckets around them" as you put it).
To convert string to double you can use str2double command:
M = str2double( M{1,:} );
You don't need to add the square brackets yourself. This just means that it is a numerical value in a cell.
In order to achieve this you should do the following, using both the num2cell as str2double functions:
newM = num2cell(str2double(Ma{1,:}))