Change string values to number in Matlab table - matlab

I am using Matlab2015b. And I would like to read a simple csv file to a table and change its string values to corresponding numeric values.
I have following example data.
Var1, VarClass
1 , attack
2 , normal
1, attack
I would like to change this string values to number. for example attack = 1, normal = -1.
My first try.
T = readtable('example_data.csv', 'Delimiter',',','FileType','text','TreatAsEmpty',{'?'});
rows_attack = strcmp(T(:,2),'attack');
T(rows_attack,2) = 1
rows_normal = strcmp(T(:,2),'normal');
T(rows_normal,2) = -1
I get following error:
Undefined function 'eq' for input arguments of type 'cell'.
What? Which undefined function? What is 'eq'?
Well. After reading some about table, I understood that supposedly higher level matlab does not override '=='. That is 'eq' which means equality. But error message certainly is not informative.
Then my second try.
T = readtable('example_data.csv', 'Delimiter',',','FileType','text','TreatAsEmpty',{'?'});
rows_attack = strcmp(T.VarClass,'attack');
T(rows_attack,2) = 1
This time, I get
Right hand side of an assignment into a table must be another table or a cell
array.
Well. Okay. It wants table. I will give it one.
T = readtable('example_data.csv', 'Delimiter',',','FileType','text','TreatAsEmpty',{'?'});
rows_attack = strcmp(T.VarClass,'attack');
rows_attack_size = sum(rows_attack);
data_to_fill = ones(rows_attack_size,1) ;
T(rows_attack,2) = array2table(data_to_fill);
Well. This time error message is.
Conversion to cell from double is not possible.
I thought that this matlab table is similar to R data-frame or python pandas DataFrame. Well, certainly it is not. Can someone guide me about how to solve this problem?

My Matlab gives different error message to your code.
>> rows_attack = strcmp(T(:,2),'attack')
rows_attack =
0
>> T(rows_attack,2) = 1
Right hand side of an assignment into a table must be another table or a cell array.
>> T(rows_attack,2)
ans =
empty 0-by-1 table
The error is multi-fold. Applying strcmp on a table does not give a vector; instead it's a scalar 0. When indexing T with zero index it gives an empty table. If neither of these is a problem, then storing a scalar double into a table is a type-not-match.
I didn't get your error message Undefined function 'eq' for input arguments of type 'cell'. from any of my trial. Maybe your matlab environment or version has a different strcmp that has a different overload for tables.
Your second try is
>> rows_attack = strcmp(T.VarClass,'attack')
rows_attack =
1
0
1
>> T(rows_attack,2) = 1
Right hand side of an assignment into a table must be another table or a cell array.
>> T(rows_attack,2)
ans =
VarClass
________
'attack'
'attack'
So this time the error is straightforward. Anyway, it looks like the desired is changing the first row to 1, since those are numbers. However, I got error
>> T(rows_attack,1) =2
Right hand side of an assignment into a table must be another table or a cell array.
Your last try works if respecting the above glitch in addressing the correct column.
>> rows_attack = strcmp(T.VarClass,'attack');
>> rows_attack_size = sum(rows_attack);
>> data_to_fill = ones(rows_attack_size,1) ;
>> T(rows_attack,2) = array2table(data_to_fill);
Conversion to cell from double is not possible.
>> data_to_fill
data_to_fill =
1
1
>> whos ans
Name Size Bytes Class Attributes
ans 2x1 1502 table
>> T(rows_attack,1) = array2table(data_to_fill);
>> T
T =
Var1 VarClass
____ ________
1 'attack'
2 'normal'
1 'attack'
>>
Also, the following also works
>> rows_attack = strcmp(T.VarClass,'attack'); T.Var1(rows_attack) = -1
T =
Var1 VarClass
____ ________
-1 'attack'
2 'normal'
-1 'attack'

Well. Thanks to #Yvon, I found my mistake and solved my problem. Following code works.
T = readtable('example_data.csv', 'Delimiter',',','FileType','text','TreatAsEmpty',{'?'});
rows_attack = strcmp(T.VarClass,'attack');
T.VarClass(rows_attack) = {-1};
rows_normal = strcmp(T.VarClass,'normal');
T.VarClass(rows_normal) = {1};
T.VarClass = cell2mat(T.VarClass);

Related

Matlab : cannot get the values of a field in a struct

I am encountering a rather weird problem. I have a big struct imported from a .mat file (it's an EEG recording):
Now let's assume I want to plot one field, I need to get the values in this field.
However, when I do this:
fieldE1 = EEG.('00 E1');
fieldE1 only becomes the last value of the field : .
If I just write in the console EEG.('00 E1'), it returns this :
ans =
-12.5850
ans =
-12.5790
ans =
-12.5760
ans =
-12.5820
ans =
-12.5890
ans =
-12.5880
ans =
-12.5880
ans =
-12.5860
On and on and on for all the values. Which explains why fieldE1 only returned the last value. I have the same behaviour when I use getfield(EEG, '00 E1') .
Any help would be appreciated.
Subscript references to a field in a struct array will return a comma-separated list. The list must be captured in array delimiters upon assignment to be used as an array:
fieldE1 = [EEG.('00 E1')];

How to sum a cell in Matlab

I am a new learner in Matlab and now want to add up a cell of column elements in Matlab, somehow "sum" function didn't work and it shows "Undefined function 'sum' for input arguments of type 'cell'", is there anyone know how to do it? MANY THANKS!:)
my data is like this:
'218148'
'106856'
'255673'
'156279'
'175589'
'310762'
'87128'
'123339'
'149070'
'104556'
'206346'
'216278'
'235786'
Your cells are strings so you first have to convert them to numeric:
C = { '218148' '106856' '255673' '156279' '175589' '310762' '87128'...
'123339' '149070' '104556' '206346' '216278' '235786' '236087'...
'99137' '123335' '130021' '101655' '98159' '102047' '824411' '63290'};
Csum = sum(str2double(C));
the result:
Csum =
4123952
You can call the content of your cells like this:
your_cell{:}
If all values are numeric, you can then group this result as a vector:
[your_cell{:}]
you can then easily sum this result:
sum([your_cell{:}])
A small example:
c{1} = 1;
c{2} = 3;
c{3} = 6;
sum([c{:}])
result:
ans =
10

How do I see the data type for each of my table's columns

For example:
>> temp = table([1; 2], {'a'; 'b'});
temp =
Var1 Var2
____ ____
1 'a'
2 'b'
Is there a way to find out what data types are in each column of this table? Does it also matter to the data types whether I used an array to create the first column and a cell array to create the second column?
EDIT: I am actually looking for a function that would accept temp as an input and return some sort of array containing the column types, for example:
>> columnType(temp)
ans = {'double' 'cell'}
While it is very good to know that class(temp.Var1) returns the column type of the first column of temp, it becomes tedious when the table has many columns.
Sure. Use class on each of the table variables to see what they look like:
>> temp = table([1; 2], {'a'; 'b'})
temp =
Var1 Var2
____ ____
1 'a'
2 'b'
>> class(temp.Var1)
ans =
double
>> class(temp.Var2)
ans =
cell
The second data type makes sense because cell arrays are designed to be containers that can store any type in each slot. You would think that you would get char as every element in your cell array is a char type, but the bigger picture is that you used a cell array to initialize the second column.
If you decided to use purely characters, specifically removing the {} braces, we get this:
>> temp = table([1; 2], ['a';'b'])
temp =
Var1 Var2
____ ____
1 a
2 b
>> class(temp.Var1)
ans =
double
>> class(temp.Var2)
ans =
char
To answer your second question, no it doesn't matter what data type goes in each column.... as long as each column has the same data type. You could have characters in one column, doubles in another, a cell array in another, uint8s in another and so on.
If you'd like to automate this and not manually check the class per variable, use varfun and apply a function to each variable in your table:
>> varfun(#class, temp, 'OutputFormat', 'cell')
ans =
'double' 'cell'

MATLAB error - ??? Attempt to reference field of non-structure array

I'm writing an insertion sort in MATLAB. I called my function like this:
>> A = [5 4 3 2 1]
A =
5 4 3 2 1
>> insertion_sort(A)
but when I run it I get the error
??? Attempt to reference field of non-structure array.
Error in ==> insertion_sort at 6
for j=2:original.length
Here's my original code:
function sorted = insertion_sort(original)
for j=2:original.length
key = original(j);
i = j-1;
while i > 0 && original(i) > key
original(i+1) = original(i);
i = i-1;
end
original(i+1) = key;
end
sorted = original;
end
Anyone know what I'm doing wrong?
Try numel(original) instead of original.length. MatLab matrices are primitive types, not objects, and they don't have a length property.
You want to use numel(original) instead of original.length. Fundamental data types don't have a length method, so MATLAB mistakenly thinks you are trying to access a field named length in a structure, which original is not.

How can I count the number of properties in a structure in MATLAB?

I have a function that returns one or more variables, but as it changes (depending on whether the function is successful or not), the following does NOT work:
[resultA, resultB, resultC, resultD, resultE, resultF] = func(somevars);
This will sometimes return an error, varargout{2} not defined, since only the first variable resultA is actually given a value when the function fails. Instead I put all the output in one variable:
output = func(somevars);
However, the variables are defined as properties of a struct, meaning I have to access them with output.A. This is not a problem in itself, but I need to count the number of properties to determine if I got the proper result.
I tried length(output), numel(output) and size(output) to no avail, so if anyone has a clever way of doing this I would be very grateful.
length(fieldnames(output))
There's probably a better way, but I can't think of it.
It looks like Matthews answer is the best for your problem:
nFields = numel(fieldnames(output));
There's one caveat which probably doesn't apply for your situation but may be interesting to know nonetheless: even if a structure field is empty, FIELDNAMES will still return the name of that field. For example:
>> s.a = 5;
>> s.b = [1 2 3];
>> s.c = [];
>> fieldnames(s)
ans =
'a'
'b'
'c'
If you are interested in knowing the number of fields that are not empty, you could use either STRUCTFUN:
nFields = sum(~structfun(#isempty,s));
or a combination of STRUCT2CELL and CELLFUN:
nFields = sum(~cellfun('isempty',struct2cell(s)));
Both of the above return an answer of 2, whereas:
nFields = numel(fieldnames(s));
returns 3.