Матовая таблица/Оптимизация типа набора данных

Я ищу некоторые оптимизированные типы данных для таблицы "наблюдения-переменные" в Matlab, которые могут быть быстро и легко доступны столбцами (через переменные) и строками (через наблюдения).

Ниже приведены сопоставления существующих типов данных Matlab:

  • Матрица работает очень быстро, hoewer, у нее нет встроенных индексирующих меток/перечислений для ее размеров, и вы не всегда можете запомнить имя переменной по индексу столбца.
  • Таблица имеет очень плохую производительность, особенно при чтении отдельных строк/столбцов в цикле for (я полагаю, что он использует некоторые медленные методы конвертирования и предназначен для большего количества Excel). li >
  • Скалярная структура (структура массивов столбцов) Тип данных - быстрый доступ к столбцам по переменным в виде векторов, но медленное последовательное преобразование в наблюдения.
  • Структура нескалярной структуры (массив структур) - быстрый последовательный доступ к наблюдениям в виде векторов, но медленное преобразование столбцов в переменные.

Интересно, могу ли я использовать более простую и оптимизированную версию типа данных таблицы, если я хочу просто комбинировать индексирование номера строки и столбцов с помощью только числовых переменных -OR- любой тип переменной.

Результаты теста script:

----
TEST1 - reading individual observations
Matrix: 0.072519 sec
Table: 18.014 sec
Array of structures: 0.49896 sec
Structure of arrays: 4.3865 sec
----
TEST2 - reading individual variables
Matrix: 0.0047834 sec
Table: 0.0017972 sec
Array of structures: 2.2715 sec
Structure of arrays: 0.0010529 sec

Тест script:

Nobs = 1e5; % number of observations-rows
varNames = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O'};
Nvar = numel(varNames); % number of variables-colums

M = randn(Nobs, Nvar); % matrix

T = array2table(M, 'VariableNames', varNames); % table

NS = struct; % nonscalar structure = array of structures
for i=1:Nobs
    for v=1:Nvar
        NS(i).(varNames{v}) = M(i,v);
    end
end

SS = struct; % scalar structure = structure of arrays
for v=1:Nvar
    SS.(varNames{v}) = M(:,v);
end

%% TEST 1 - reading individual observations (row-wise)
disp('----'); disp('TEST1 - reading individual observations');

tic; % matrix
for i=1:Nobs
   x = M(i,:); end
disp(['Matrix: ', num2str(toc()), ' sec']);

tic; % table
for i=1:Nobs
   x = T(i,:); end
disp(['Table: ', num2str(toc), ' sec']);

tic;% nonscalar structure = array of structures
for i=1:Nobs
    x = NS(i); end
disp(['Array of structures: ', num2str(toc()), ' sec']);

tic;% scalar structure = structure of arrays 
for i=1:Nobs
    for v=1:Nvar
        x.(varNames{v}) = SS.(varNames{v})(i);
    end
end
disp(['Structure of arrays: ', num2str(toc()), ' sec']);

%% TEST 2 - reading individual variables (column-wise)
disp('----'); disp('TEST2 - reading individual variables');

tic; % matrix
for v=1:Nvar
   x = M(:,v); end
disp(['Matrix: ', num2str(toc()), ' sec']);

tic; % table
for v=1:Nvar
   x = T.(varNames{v}); end
disp(['Table: ', num2str(toc()), ' sec']);

tic; % nonscalar structure = array of structures
for v=1:Nvar
    for i=1:Nobs
        x(i,1) = NS(i).(varNames{v});
    end
end
disp(['Array of structures: ', num2str(toc()), ' sec']);

tic; % scalar structure = structure of arrays
for v=1:Nvar
    x = SS.(varNames{v}); end
disp(['Structure of arrays: ', num2str(toc()), ' sec']);

Ответ 1

Я бы использовал матрицы, так как они самые быстрые и простые в использовании, а затем создают набор перечислимых меток столбцов, чтобы упростить индексирование столбцов. Вот несколько способов сделать это:


Используйте объект containers.Map:

Учитывая ваши имена переменных и предполагая, что они отображаются в порядке от столбцов от 1 до N, вы можете создать такое сопоставление:

varNames = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O'};
col = containers.Map(varNames, 1:numel(varNames));

И теперь вы можете использовать карту для доступа к столбцам ваших данных по имени переменной. Например, если вы хотите получить столбцы для переменных A и C (т.е. Первый и третий) из матрицы data, вы должны сделать это:

subData = data(:, [col('A') col('C')]);


Используйте struct:

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

enumData = [varNames; num2cell(1:numel(varNames))];
col = struct(enumData{:});

И вот что col содержит:

struct with fields:

  A: 1
  B: 2
  C: 3
  D: 4
  E: 5
  F: 6
  G: 7
  H: 8
  I: 9
  J: 10
  K: 11
  L: 12
  M: 13
  N: 14
  O: 15

И вы получите доступ к столбцам A и C следующим образом:

subData = data(:, [col.A col.C]);
% ...or with dynamic field names...
subData = data(:, [col.('A') col.('C')]);


Сделайте кучу переменных:

Вы можете просто создать переменную в своей рабочей области для каждого имени столбца и сохранить в ней индексы столбцов. Это будет загрязнять ваше рабочее пространство с помощью большего количества переменных, но дает вам краткое описание доступа к данным столбца. Вот простой способ сделать это, используя сильно оскорбленный eval:

enumData = [varNames; num2cell(1:numel(varNames))];
eval(sprintf('%s=%d;', enumData{:}));

И доступ к столбцам A и C выполняется так же легко, как:

subData = data(:, [A C]);


Используйте класс перечисления:

Это, вероятно, хорошая доза избытка, но если вы собираетесь использовать одно и то же сопоставление меток столбцов и индексов для многих анализов, вы можете создать класс перечисления, сохраните его где-нибудь на своем путь MATLAB, и вам больше не придется беспокоиться о том, чтобы снова определить свои столбцы. Например, здесь класс ColVar с 15 перечисляемыми значениями:

classdef ColVar < double
  enumeration
    A (1)
    B (2)
    C (3)
    D (4)
    E (5)
    F (6)
    G (7)
    H (8)
    I (9)
    J (10)
    K (11)
    L (12)
    M (13)
    N (14)
    O (15)
  end
end

И вы получите доступ к столбцам A и C следующим образом:

subData = data(:, [ColVar.A ColVar.C]);