Почему изменение имени переменной таблицы не работает, если это свойство класса?

В прошлом я широко использовал класс table Matlab. Этот очень простой код внутри скрипта или в приглашении работает так, как ожидалось:

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

Теперь у меня такой же table, как property у 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

Если я выполню следующее в командной строке, zeros будут назначены table, но VariableNames сохранят свое значение по умолчанию, т. е. {'Var1', 'Var2'} и т. д.

tc = TestClass; tc.testMethod

Даже tc.testTable.Properties.VariableNames = varNames их не меняет.

Это баг, или я что-то пропустил? (Я использую Matlab R2017b)


person rotton    schedule 24.01.2018    source источник
comment
Это может быть ошибка с принудительным применением типа/размера, проблема исчезает, когда вы удаляете его. Я бы посоветовал подать отчет об ошибке.   -  person excaza    schedule 24.01.2018
comment
Это определенно ошибка с принудительным размером, даже указание значения таблицы по умолчанию с явными именами переменных перезаписывается 'Var1', 'Var2', ..., но работает, как и ожидалось, как только принудительное ограничение размера удаляется.   -  person excaza    schedule 24.01.2018
comment
testTable (:,3) table означает, что это должен быть массив таблиц размером 3 на 3, а не таблица 3 на 3. У вас не может быть массивов таблиц, поэтому это ограничение не имеет смысла. Используйте явную функцию проверки подлинности, как это предлагается в ответе @excaza.   -  person Sam Roberts    schedule 24.01.2018
comment
Mathworks подтвердил, что это ошибка   -  person excaza    schedule 26.01.2018


Ответы (1)


Похоже, это ошибка в проверка размера свойства, поскольку поведение исчезает при его удалении:

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

Пока TMW не исправит ошибку, ее можно обойти с помощью пользовательской функции проверки, чтобы сохранить желаемое поведение:

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
person excaza    schedule 24.01.2018
comment
Я не уверен, что точно описал бы это как ошибку, но это определенно неясное поведение. Свойство size (:,3) говорит, что testTable должен быть массивом таблиц размерностью 3 на 3 (не таблицей размером 3 на 3); но поскольку у вас не может быть массивов таблиц, это не имеет смысла как ограничение. Я бы предположил, что это ошибка документации, а не ошибка. В любом случае ваше предложение использовать функцию проверки — это правильный способ добиться того, к чему стремится OP. Может, назовем его mustHaveThreeVars, а не TheEnforcer? - person Sam Roberts; 24.01.2018
comment
Я не согласен с вашим утверждением о том, что означает размер свойства для таблиц. Помимо поведения имени переменной, проверка размера работает должным образом. Это абсолютно ошибка. - person excaza; 24.01.2018
comment
Я предполагаю, что если проверка размера частично работает с table, то это удача, а не явный дизайн - поэтому, если она также частично не работает, то это не совсем ошибка (хотя я понимаю почему вы так думаете). И что, если вы отправите отчет об ошибке, держу пари, MathWorks исправит это, изменив документацию, чтобы сказать что-то вроде не выполнять проверку размера свойства с классами, которые перегрузили size необычным образом, например table, потому что размер свойства предназначен означать, что это фактический массив класса. - person Sam Roberts; 24.01.2018
comment
Но в любом случае - отчет об ошибке был бы полезен, даже если он приводит к более четкой документации, а не к изменению функциональности. - person Sam Roberts; 24.01.2018
comment
Это бессмысленная оговорка. Метод проверки правильного размера должен возвращать соответствующий результат без вызова subasgn. По крайней мере, когда subasgn клонирует таблицу, она должна сохранять имена переменных, чего не происходит. - person excaza; 24.01.2018
comment
Только представьте, если бы вы создали класс, который перегружает size для вызова rand, и использовали его там, где table используется здесь. Должны быть некоторые ограничения на классы, которые вы можете использовать для свойств с ограничениями по размеру, и если вы нарушите эти ограничения, произойдет что-то странное. Я предполагаю, что здесь происходит что-то подобное, и что правильным решением является более четкое документирование этих ограничений (что может быть таким же простым, как не использовать классы с перегруженным size). В любом случае - не нужно спорить, вы дали правильный обходной путь и получили мой голос. - person Sam Roberts; 24.01.2018