Is there a way to create a table with multi-line column names? - matlab

I am attempting to create a table that has the following format of multi line heading for the columns
|Col1 Co2 Col3|
|Col1 Co2 Col3|
Tried this using the example and adding a | between 1st and 2nd line but did not work
T = table(categorical({'M';'F';'M'}),[45;32;34],...
{'NY';'CA';'MA'},logical([1;0;0]),..
'VariableNames',{'Gender|Gender2','Age|Age2','State|State2','Vote|Vote2'})
I am using R2018b student edition

The ability to have arbitrary variable names in tables was added to release R2019b of MATLAB. Using that release, your code works as expected and produces:
T =
3×4 table
Gender|Gender2 Age|Age2 State|State2 Vote|Vote2
______________ ________ ____________ __________
M 45 {'NY'} true
F 32 {'CA'} false
M 34 {'MA'} false
However, in your question you state that you want multi-line variables. You can make these in R2019b, but the display collapses the newline character into a ↵, like this:
>> T = table(1, 'VariableNames', {['a', newline, 'b']})
T =
table
a↵b
___
1
If it's just the display you're after, you could consider making nested tables, like this:
t1 = table(1);
t2 = table(2);
T = table(t1, t2)
which results in:
T =
1×2 table
t1 t2
Var1 Var1
____ ____
1 2
Note that that final approach works in R2019a and prior releases.

No can do. Valid variable names of tables are similar to other variables in Matlab. They cannot contain \n (new-line) or anything which is not letters and numbers. Underscore is the exception.

Related

readtable on text file ignores first row which contains the column names

I have a tab delimited text file which contains some data organised into columns with the first row acting as column names such as:
TN Stim Task RT
1 A A 500.2
2 B A 569
3 C A 654
and so on.
I am trying to read this textfile into MATLAB(r2018a) using readtable with
Data1 = readtable(filename);
I manage to get all the data in Data1 table, but the column names are showing as Var1, Var2 etc. If I use Name Value pairs to specify to read first row as column names as in:
Data1 = readtable(filename, 'ReadVariableNames', true);
then I get the column names as the first data row, i.e.
1 A A 500.2
So it just looks like it is ignoring the first row completely. How can I modify the readtable call to use the entries on the first row as column names?
I figured it out. It appears there was an additional tab in some of the rows after the last column. Because of this, readtable was reading it as an additional column, but did not have a column name to assign to it. It seems that if any of the column names are missing, it names them all as Var1, Var2, etc.
Based on the way your sample file text is formatted above, it appears that the column labels are separated by spaces instead of by tabs the way the data is. In this case, readtable will assume (based on the data) that the delimiter is a tab and treat the column labels as a header line to skip. Add tabs between them and you should be good to go.
Test with spaces between column labels:
% File contents:
TN Stim Task RT
1 A A 500.2
2 B A 569
3 C A 654
>> Data1 = readtable('sample_table.txt')
Data1 =
Var1 Var2 Var3 Var4 % Default names
____ ____ ____ _____
1 'A' 'A' 500.2
2 'B' 'A' 569
3 'C' 'A' 654
Test with tabs between column labels:
% File contents:
TN Stim Task RT
1 A A 500.2
2 B A 569
3 C A 654
>> Data1 = readtable('sample_table.txt')
Data1 =
TN Stim Task RT
__ ____ ____ _____
1 'A' 'A' 500.2
2 'B' 'A' 569
3 'C' 'A' 654

Creating table with multiple row and column names

I'm trying to create a table in matlab, with rows and columns which have several 'levels' of names, par example column name 'Neutral' which is divided into sublevels 'M' and 'SD' (see below for an illustration). I have the same problem with rows. Does anyone know if this is possible in Matlab, and if yes, how?
| Neutral |<- Column name
|----|----|
| M | SD |<- Sublevel of column name
|----|----|
|5.70|2.39|<- Data
|7.37|2.27|<-
| .. | .. |<-
| .. | .. |<-
You can nest table objects, like so:
t = table(table((1:10)', rand(10,1), 'VariableNames', {'M', 'SD'}), ...
'VariableNames', {'Neutral'});
The display looks a little odd, but you can index the nested variables in the way that you might expect, i.e. t.Neutral.M etc.

Join tables with non-equal rows in Matlab

I'm trying to use the relatively new data type in Matlab, table. I have a number of variables that each contains a value for a set of parameters (Rows). The rows are not (necessarily) equal for each variable, however. I want to join the variables together so the results are all displayed in a single table. E.g., I want to join these together: (drawn side by side to save space)
Var_A Var_B
________ _______
a 0.36744 b 0.88517
b 0.98798 c 0.91329
c 0.037739 d 0.79618
Is it possible to join these two tables?
Here's an example of what I'm trying to do:
A = table(rand(3,1),'VariableNames',{'Var_A'},'RowNames',{'a','b','c'})
B = table(rand(3,1),'VariableNames',{'Var_B'},'RowNames',{'b','c','d'})
try
C = join(A,B)
catch e
disp(e.identifier)
disp(e.message)
end
This results in:
MATLAB:table:join:CantInferKey
Cannot find a common table variable to use as a key variable.
Okay, so maybe join isn't intended for this -- what about outerjoin? Its documentation sounds promising:
The outer join includes the rows that match between A and B, and also unmatched rows from either A or B, all with respect to the key variables. C contains all variables from both A and B, including the key variables.
Well, outerjoin apparently can't be used with tables with row names! This is the closest I've found that does what I want, but seems to be against the idea of the table data structure to some degree:
AA = table({'a';'b';'c'},rand(3,1));
AA.Properties.VariableNames = {'param','Var_A'}
BB = table({'b';'c';'d'},rand(3,1));
BB.Properties.VariableNames = {'param','Var_B'}
CC = outerjoin(AA,BB,'Keys',1,'MergeKeys',true)
This results in
param Var_A Var_B
_____ _______ _______
'a' 0.10676 NaN
'b' 0.65376 0.77905
'c' 0.49417 0.71504
'd' NaN 0.90372
I.e., the row is just stored as a separate variable. This means it can't be indexed using "logical" notation such as CC{'a',:}.
So this can be fixed with:
CCC = CC(:,2:end);
CCC.Properties.RowNames = CC{:,1}
Which finally results in:
CCC =
Var_A Var_B
_______ ________
a 0.4168 NaN
b 0.65686 0.29198
c 0.62797 0.43165
d NaN 0.015487
But is this really the best way to go about things? Matlab is weird.
There must be a better way to do this, but here is another option:
clear;
%// Create two tables to play with.
tableA = table([.5; .6; .7 ],'variablenames',{'varA'},'rowname',{'a','b','c'});
tableB = table([.55; .62; .68],'variablenames',{'varB'},'rowname',{'b','c','d'});
%// Lets add rows to tableA so that it has the same rows as tableB
%// First, get the set difference of tableB rows and tableA rows
%// Then, make a new table with those rows and NaN for data.
%// Finally, concatenate tableA with the new table
tableAnewRows=setdiff(tableB.Properties.RowNames,tableA.Properties.RowNames);
tableAadd=table( nan(length(tableAnewRows),1) ,'variablenames',{'varA'},'rownames',tableAnewRows);
tableA=[tableA;tableAadd];
%// Lets add rows to tableB so that it has the same rows as tableA
tableBnewRows=setdiff(tableA.Properties.RowNames,tableB.Properties.RowNames);
tableBadd=table( nan(length(tableBnewRows),1) ,'variablenames',{'varB'},'rownames',tableBnewRows);
tableB=[tableB;tableBadd];
%// Form tableC from tableA and tableB. Could also use join().
tableC=[tableA tableB];

Filter on parts of words in Matlab tables

Similar to Excel, I need to find out how to filter out rows of a table that do not contain a certain string.
For example, I need only rows that contain the letters "MX". Within the sheet, there are rows with strings like ZMX01, MX002, and US001. I would want the first two rows.
This seems like a simple question, so I am surprised I couldn't find any help for this!
It is similar to the question Filter on words in Matlab tables (as in Excel)
You may not find a lot of information on tables in MATLAB, as they were introduced with version R2013a, which is not that long ago. So, about your question: Let's first create a sample table:
% Create a sample table
col1 = {'ZMX01'; 'MX002'; 'US001'};
col2 = {5;7;3};
T = table(col1, col2);
T =
col1 col2
_______ ____
'ZMX01' [5]
'MX002' [7]
'US001' [3]
Now, MATLAB provides the rowfun function to apply any function to each row in a table. By default, the function you call has to be able to work on all columns of the table.
To only apply rowfun to one column, you can use the 'InputVariables' parameter, which lets you specify either the number of the column (e.g. 2 for the second column) or the name of the column (e.g. 'myColumnName').
Then, you can set 'OutputFormat' to 'uniform' to get an array and not a new table as output.
In your case, you'll want to use strfind on the column 'col1'. The return value of strfind is either an empty array (if 'MX' wasn't found), or an array of all indices where 'MX' was found.
% Apply rowfun
idx = rowfun(#(x)strfind(x,'MX'), T, 'InputVariables', 'col1', 'OutputFormat', 'uniform');
The output of this will be
idx =
[2]
[1]
[]
i.e. a 3-by-1 cell array, which is empty for 'US001' and contains a positive value for both other inputs. To create a subset of the table with this data, we can do the following:
% Create logical array, which is true for all rows to keep.
idx = ~cellfun(#isempty, idx);
% Save these rows and all columns of the table into a new table
R = T(idx,:);
And finally, we have our resulting table R:
R =
col1 col2
_______ ____
'ZMX01' [5]
'MX002' [7]

How to export a table with row names from Matlab to Excel?

I am trying to export a table from Matlab to Excel with the names of the rows. Here is a (very) simplified version of my table:
T = table(1,5,2);
T.Properties.RowNames = {'Number'}
T =
Var1 Var2 Var3
____ ____ ____
Number 1 5 2
If I apply Matlab's instructions for exporting a table:
filename = 'data.xlsx';
writetable(T,filename,'Sheet',1,'Range','D1')
it leaves out my row name "Number" and only exports the variables:
Var1 Var2 Var3
____ ____ ____
1 5 2
Is there a way to export a table including row names from Matlab?
You need to use the WriteRowNames optional input
writetable(T,filename,'Sheet',1,'Range','D1','WriteRowNames',true)