How to read tables out of a MAT file?

Normally, this is how I read a variable out of a MAT file:

using MAT
F1 = matopen("test.mat");
Var1 = read(F1, "Var1");
close(F1);

Now I have some Matlab tables stored in the MAT file. Below is an example:

 Name             Size                    Bytes        Class    Attributes
   T1            28206x73            22997697     table

How do I read the table T1 out? Once I read it out, how do I access each of the column data?

Here is a test mat file containing a table called T1:

Many thanks!

1 Like

Check this example to see if it helps:

using MAT
M = rand(3,3)
file = matopen("matfile.mat", "w")
write(file, "Mout", M)
close(file)

vars = matread("matfile.mat")  # check variable name in Dict is "Mout"
M = vars["Mout"]

3ร—3 Matrix{Float64}:
 0.0139301  0.538621  0.564867
 0.939367   0.120995  0.0989636
 0.96166    0.902847  0.837158
1 Like

Not familiar with Matlab tables, but they look like dataframes.

However inspecting your file above it shows objects with different lengths?

vars = matread("test.mat")   # check variable names in Dict
dic = vars["__opaque__"]

Dict{String, Any} with 4 entries:
  "s1"  => Int8[77, 67, 79, 83]
  "arr" => ("", UInt32[0xdd000000; 0x00000002; โ€ฆ ; 0x00000001; 0x00000001;;])
  "s0"  => Int8[84, 49]
  "s2"  => Int8[116, 97, 98, 108, 101]

If they were a proper table, then in Julia you could use DataFrames constructor to build a dataframe from the Dict:

df = DataFrame(dic)

Sorry, my limits have been reached here.

Many thanks for the reply!

This is what my table looks like inside Matlab:

T1 =

100ร—6 table

CTDPRES    Depth    CTDTEMP_ITS90    CTDTEMP_flag    CTDSAL_PSS78    CTDSAL_flag
_______    _____    _____________    ____________    ____________    ___________

  115      113.9        2.199             2             32.761            2     
  101      100.1        2.098             2             32.739            2     
   60       59.4        1.637             2             32.662            2     
   42       41.6        0.763             2             32.515            2     
   31       30.7       -0.318             2             32.217            2     
   20       19.8        -0.45             2             32.156            2     
   11       10.9       -0.444             2             32.158            2     
    5          5        -0.44             2             32.158            2     
  102        101        1.302             2             32.598            2

It seems that MATLAB tables are not supported by the MAT.jl package, see here.

1 Like

So bad the MAT package canโ€™t do it now. I hope someone will make this happen soon.

This doesnโ€™t do what you wanted, load a table from MAT file. But I wanted to see if it is possible with MATLAB.jl (needs a MATLAB installation)
Basically I had to use MATLAB to do all the data conversion to data types that are supported: convert the table content to cell, convert headers to array of string. Then, rebuild it with DataFrame.

using MATLAB
using DataFrames
mxcall(:load,0,"patients")
mat"patients = table(Gender,Age,Height,Weight,Smoker,Systolic,Diastolic);"
data = mat"table2cell(patients)"
headers = mat"patients.Properties.VariableNames"
df = DataFrame([headers[c]=>data[:,c] for c in 1:length(headers)])
julia> df
100ร—8 DataFrame
 Row โ”‚ LastName    Gender  Age   Height  Weight  Smoker  Systolic  Diastolic
     โ”‚ Any         Any     Any   Any     Any     Any     Any       Any
โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
   1 โ”‚ Smith       Male    38.0  71.0    176.0   true    124.0     93.0
   2 โ”‚ Johnson     Male    43.0  69.0    163.0   false   109.0     77.0
   3 โ”‚ Williams    Female  38.0  64.0    131.0   false   125.0     83.0
   4 โ”‚ Jones       Female  40.0  67.0    133.0   false   117.0     75.0
   5 โ”‚ Brown       Female  49.0  64.0    119.0   false   122.0     80.0
   6 โ”‚ Davis       Female  46.0  68.0    142.0   false   121.0     70.0
   7 โ”‚ Miller      Female  33.0  64.0    142.0   true    130.0     88.0
   8 โ”‚ Wilson      Male    40.0  68.0    180.0   false   115.0     82.0
   9 โ”‚ Moore       Male    28.0  68.0    183.0   false   115.0     78.0
  10 โ”‚ Taylor      Female  31.0  66.0    132.0   false   118.0     86.0
  11 โ”‚ Anderson    Female  45.0  68.0    128.0   false   114.0     77.0
  12 โ”‚ Thomas      Female  42.0  66.0    137.0   false   115.0     68.0
  13 โ”‚ Jackson     Male    25.0  71.0    174.0   false   127.0     74.0
  14 โ”‚ White       Male    39.0  72.0    202.0   true    130.0     95.0
  โ‹ฎ  โ”‚     โ‹ฎ         โ‹ฎ      โ‹ฎ      โ‹ฎ       โ‹ฎ       โ‹ฎ        โ‹ฎ          โ‹ฎ
  88 โ”‚ Hughes      Female  49.0  63.0    123.0   true    128.0     96.0
  89 โ”‚ Flores      Female  31.0  66.0    141.0   true    123.0     87.0
  90 โ”‚ Washington  Female  37.0  65.0    129.0   false   122.0     81.0
  91 โ”‚ Butler      Male    38.0  68.0    184.0   true    138.0     90.0
  92 โ”‚ Simmons     Male    45.0  71.0    181.0   false   124.0     77.0
  93 โ”‚ Foster      Female  30.0  70.0    124.0   false   130.0     91.0
  94 โ”‚ Gonzales    Male    48.0  71.0    174.0   false   123.0     79.0
  95 โ”‚ Bryant      Female  48.0  66.0    134.0   false   129.0     73.0
  96 โ”‚ Alexander   Male    25.0  69.0    171.0   true    128.0     99.0
  97 โ”‚ Russell     Male    44.0  69.0    188.0   true    124.0     92.0
  98 โ”‚ Griffin     Male    49.0  70.0    186.0   false   119.0     74.0
  99 โ”‚ Diaz        Male    45.0  68.0    172.0   true    136.0     93.0
 100 โ”‚ Hayes       Male    48.0  66.0    177.0   false   114.0     86.0
                                                              73 rows omitted
4 Likes

Iโ€™ve long ceased needing to read Matlab files, but I fear my work from 2014 might still be state of the art.

In short, Iโ€™d bet tables (which are newer than that work) are just Matlab class objects. And thus they get saved in that same undocumented manner as I was attempting to reverse-engineer above. See also this python question seeking the same thing.

3 Likes

Many thanks, Derrick!

You used โ€œ0โ€ and โ€œpaitentsโ€. Iโ€™m not sure what they are. If my MAT file is located here: F1 = "/Path/test.mat");

And the table that is stored within this mat file is called T1. How would I write this code to read out T1?

Some quick usage:
https://github.com/JuliaInterop/MATLAB.jl#use-matlab-engine

I chose to use mxcall and mat""just out of my preference.
So here is the MATLAB evaluation I wanted

load('patients')

this is an example table dataset came with MATLAB (found it in table doc)

mxcall has this signature:

  1. the MATLAB function you wish to call as a symbol, in this case, it is :load
  2. number of output I am expecting, in this case, I just want to load it into workspace, so its is 0
  3. the arguments, it is a string in MATLAB, so I could define it in Julia string, which is supported for conversion

so in your case, I would guess it is this:

mxcall(:load, 0, "/Path/test.mat")
data = mat"table2cell(T1)"
headers = mat"T1.Properties.VariableNames"
df = DataFrame([headers[c]=>data[:,c] for c in 1:length(headers)])
2 Likes

Many thanks! Unfortunately, Iโ€™m getting the below error:

LoadError: MATLAB.MEngineError("failed to get variable ans from MATLAB session")

Stacktrace:

[1] **get_mvariable(** session::MSession, name::Symbol **)**
@ MATLAB ~/.julia/packages/MATLAB/T20Ly/src/engine.jl:164
[2] **get_mvariable**
@ ~/.julia/packages/MATLAB/T20Ly/src/engine.jl:168 [inlined]
[3] **get_variable(** name::Symbol **)**
@ MATLAB ~/.julia/packages/MATLAB/T20Ly/src/engine.jl:170
[4] top-level scope
@ ~/.julia/packages/MATLAB/T20Ly/src/matstr.jl:169

The error suggested that one or both of these line didnโ€™t return a variable ans

data = mat"table2cell(T1)"
headers = mat"T1.Properties.VariableNames"

MATLAB.jl basically a non-desktop session of MATLAB, after the load command, you could do this to see if it load the data into workspace.

mat"whos"

By the way, I forgot a command in my earlier post.
FYI, I have R2017.

1 Like