MATLAB: Find numeric columns in a cell array - matlab

I would like to use gplotmatrix on a dataset data, which contains mixed data (numeric and strings). However, gplotmatrix works on numeric data, so I need to convert my dataset to a matrix. As far as I know, the only way is to do this is through
C=dataset2cell(data)
X=cell2mat(C)
However, the second command throws an error, because C contains non-numeric columns. Is there a way to find which columns of a cell array are purely numeric?

Use cellfun with #isnumeric function handle -
numeric_cols = find(all(cellfun(#isnumeric,C)))
Related useful pointers -
function_handle
Anonymous Functions

Related

Can i write out a txt or csv doc with data of varying dimensions in Matlab?

I am using Matlab R2013b.
I have a 100x100 matrix which contains both numbers and strings. I converted it to a cell array (alldat) and wrote it to a csv file (blah.csv).
I then tried to append a single number to the top line of this csv file...which Matlab won't let me do.
cell2csv('blah.csv',alldat)
I can append the single number 'n' at the bottom of the matrix:
dlmwrite('blah.csv',n,'-append','delimiter',' ','roffset',1)
But it won't let me do it the other way around (so I can put the number in the first cell of the csv file, then have the matrix below it.
Can anyone advise?
I also tried outputting the cell array to a txt document using dlmwrite:
dlmwrite('blah.txt',alldat,'delimiter',' ');
And I kept getting this error:
Error using dlmwrite (line 113) The input cell array cannot be
converted to a matrix.
I often use tables for such tasks. Since you have a 100 x 100 array and not variables with different dimensions, it should be possible to adapt.
VarA={'12A3';123;'12B3'};
VarB={'45A6';456;'45B6'};
T=table(VarA,VarB);
writetable(T,'test.csv','WriteVariableNames',false)
T1=readtable('test.csv','ReadVariableNames',false)
You may want to use cell2table to create a table directly from your cell array, although it didn't work for me because it made some strange conversions from number to character.

How to rename table variables in Matlab?

I would like to create a table from a matrix of spectra data, using a specific list of variables (column, which here correspond to 1000 spectral wavelenght values) instead of putting the name manually.
To do so, i use the array2table function, and matlab documentation shows that names for rows and label of variables must be put as cell arrays, (and not matrix). So I need to first convert my x-axis (spectral wavelenght) to a cell array. I use the following:
C = num2cell(xaxis); % to convert into a cell array (each cell contain 1 value)
isvarname C % to check that the variable is valid as a cell array
T = array2table(R,'RowNames', concentration,'VariableNames',C);
Here: R is the matrix, concentration is a Cell array 1x500, xaxis is the wavelenght of spectral data 1x1000 (which is ranged from 600 to 1800, approx. there is no null value).
Unfortunately, I got the following error:
"Error using array2table (line 62)
The VariableNames property must be a cell array, with each element containing one nonempty string."
which means I can input properly the columns (variable) names (while row names, however, works fine).
Note: i tried the
T.Properties.VariableNames = c but it is not working either.
I checked the other post on table name value but its not helping,
Any thought about this?
Thank you very much.
Maybe you mistyped your question's code, but it seems that you are using the array xaxis instead of C. Anyway, I suggest you try casting the cells content to strings this way
T = array2table(R,'RowNames', concentration,'VariableNames',cellfun(#(x)num2str(x),num2cell(xaxis),'uniformoutput',false));
Edit
Looking through the table docs it says that
Variable names, specified as the comma-separated pair consisting of 'VariableNames' and a cell array of character vectors that are nonempty and distinct. The number of character vectors must equal the number of variables. The variable names that you assign must be valid MATLABĀ® variable names. You can determine valid variable names using the function isvarname.
Furthermore, the isvarname function says that
A valid variable name begins with a letter and contains not more than namelengthmax characters. Valid variable names can include letters, digits, and underscores. MATLAB keywords are not valid variable names. To determine if the input is a MATLAB keyword, use the iskeyword function.
This means that you cannot use the xaxis values as variable names by themselves, you need to, at least, prepend a character and remove the decimal dot. You can do so with the following
T = array2table(R,'RowNames', concentration,...
'VariableNames',cellfun(#(x)['wavel_',regexprep(num2str(x),'.','_')],num2cell(xaxis),'uniformoutput',false));
This code will prepend 'wavel_' to the numerical string value. It will also replace the dots with underscores using the regexprep function. However, it seems like this is really unnecessary because the column names are not really informative. The array2table function's doc says that if you don't supply the 'variableNames' option it will do the following:
If valid MATLAB identifiers are not available for use as variable names, MATLAB uses a cell array of N character vectors of the form {'Var1' ... 'VarN'} where N is the number of variables.
Maybe using the default variable names is good enough.

error in array of struct matlab

I want to train data on various labels using svm and want svm model as array of struct. I am doing like this but getting the error:
Subscripted assignment between dissimilar structures.
Please help me out
model = repmat(struct(),size);
for i=1:size
model(i) = svmtrain(train_data,labels(:,i),'Options', options);
end
A structure array in MATLAB can only contain structures with identical fields. By first creating an array of empty structures1 and then trying to fill it with SVMStruct structures, you try to create a mixed array with some empty structures, and some SVMStruct structures. This is not possible, thus MATLAB complains about "dissimilar structures" (not-equal structures: empty vs. SVMStruct).
To allocate an array of structs, you will have to specify all fields during initialization and fill them all with initial values - which is rather inconvenient in this case. A very simple alternative is to drop this initialization, and run your loop the other way around2,3:
for ii=sizeOfLabels:-1:1
model(ii) = svmtrain(train_data,labels(:,ii),'Options', options);
end
That way, for ii=sizeOfLabels, e.g. ii=100, MATLAB will call model(100)=..., while model doesn't exist yet. It will then allocate all space needed for 100 SVMStructs and fill the first 99 instances with empty values. That way you pre-allocate the memory, without having to worry about initializing the values.
1Note: if e.g. size=5, calling repmat(struct(),size) will create a 5-by-5 matrix of empty structs. To create a 1-by-5 array of structs, call repmat(struct(),1,size).
2Don't use size as a variable name, as this is a function. If you do that, you can't use the size function anymore.
3i and j denote the imaginary unit in MATLAB. Using them as a variable slows the code down and is error-prone. Use e.g. k or ii for loops instead.

Passing Struct elements of variable lengths into a matrix Matlab

I am parshing a few data via the internet. The struct Data has several elements. I am interested in Data.Value a call of Data(1,1).Value is a double vector of [56,1]. Moving on to the second struct cell Data(1,2).Value is a double vector [46,1].
Writing a FOR Loop to get the entire Data(1,i).Value from 1 to 500, when it come to the second element, I get the following error returned: Subscripted assignment dimension mismatch.
Although I understand the error I cannot justify it and hence I cannot work out a solution.
I have also tried to pre-define a matrix of variable sizes to overcome this, without result.
Anybody can think of any solution to get the entire Data(1,:).Value
Thanks a lot for the contribution guys.
You can use
vertcat(Data(1,:).Value)
to create a column vector made by concatenating Data(1,1).Value, Data(1,2).Value, ...
Alternatively, you can use the generalized concatenation operator
cat(1, Data(1,:).Value)

How to convert Matlab string CSV of cell into separate columns of a matrix?

If I have a Matlab CELL line of string characters separated by a comma like:
12/28/2012,00:00:01,0.99458,1,10518,0.99458,0.99483,0,0,0,0,-,-,-,b,-,C
How do I separate each one into its own column within a matrix? What is the most efficient way of doing this?
Can this be done?
Thanks
UPDATE: Just realized this question duplicates how-to-convert-comma-separated-string-to-cell-array-of-strings-in-matlab and that my answer duplicates the answer provided by #Jonas. I'm flagging it as a duplicate.
Here is the most efficient method I'm aware of:
%# Build your string
Input = '12/28/2012,00:00:01,0.99458,1,10518,0.99458,0.99483,0,0,0,0,-,-,-,b,-,C';
%# Convert to cell array of strings
Output = regexp(Input, '([^,]*)', 'tokens');
Output = cat(2, Output{:});
Some points to note:
1) Note, this will work whether Input is a character array (ie a string) or a cell containing a character array.
2) I've assumed you want the output to be a cell array of strings. Offhand, I can't think of another way of grouping strings of differing length into separate columns using Matlab without building your own custom class.
3) The solution provided by #IlyaKobelevskiy will group the strings into separate rows (not columns) and thus essentially limits you to only a single observation.
Assuming str is your cell line:
str ={'12/28/2012,00:00:01,0.99458,1,10518,0.99458,0.99483,0,0,0,0,-,-,-,b,-,C'};
ind=strfind(str{1},',');
len=diff([0 ind]);
sz=max(len);
A=zeros(length(ind),sz);
prev=1;
for i=1:length(ind)
A(i,1:len(i)-1)=str{1}(prev:(ind(i)-1));
prev=ind(i)+1;
end;
A=char(A);
Not sure if it is the most efficient way, but should work...