Search code examples
matlabmatlab-classmatlab-table

Why does changing the Variable Name of a Table not work if it's the Property of a Class?


In the past, I've been making extensive use of Matlab's table class. This very simple code, inside a script or at the prompt, works as expected:

varNames = {'Date_time', 'Concentration_1', 'Concentration_2'};
testTable = array2table(zeros(5,3), 'VariableNames', varNames)

Now, I have the same table as the property of a handle class.

classdef TestClass < handle
    properties
        testTable (:,3) table
    end
    methods
        function testMethod(obj)
            varNames = {'Date_time', 'Concentration_1', 'Concentration_2'};
            obj.testTable = array2table(zeros(5,3), 'VariableNames', varNames);
            obj.testTable.Properties.VariableNames
        end
    end
end

If I execute the following at the command prompt, the zeros are assigned to the table, but the VariableNames keep their default value, i.e., {'Var1', 'Var2'} etc.

tc = TestClass; tc.testMethod

Even tc.testTable.Properties.VariableNames = varNames does not change them.

Is this a bug, or am I missing something? (I am using Matlab R2017b)


Solution

  • This appears to be a bug with MATLAB's property size validation, as the behavior disappears when it is removed:

    classdef SOcode < handle
        properties
            testTable(:,3) = table(1, 2, 3, 'VariableNames', {'a', 'b', 'c'});
        end
    end
    
    >> asdf.testTable
    
    ans =
    
      1×3 table
    
        Var1    Var2    Var3
        ____    ____    ____
    
        1       2       3
    

    vs.

    classdef SOcode < handle
        properties
            testTable = table(1, 2, 3, 'VariableNames', {'a', 'b', 'c'});
        end
    end
    
    >> asdf.testTable
    
    ans =
    
      1×3 table
    
        a    b    c
        _    _    _
    
        1    2    3
    

    Until TMW resolves the bug, this can be worked around with a custom validation function in order to preserve the desired behavior:

    classdef SOcode < handle
        properties
            testTable table {TheEnforcer(testTable)}
        end
        methods
            function testMethod(obj)
                varNames = {'Date_time', 'Concentration_1', 'Concentration_2', 'hi'};
                obj.testTable = array2table(zeros(5,4), 'VariableNames', varNames);
                obj.testTable.Properties.VariableNames
            end
        end
    end
    
    function TheEnforcer(inT)
    ncolumns = 3;
    if ~isempty(inT)
        if size(inT, 2) ~= ncolumns
            error('An Error')
        end
    end
    end