Матовая таблица/Оптимизация типа набора данных
Я ищу некоторые оптимизированные типы данных для таблицы "наблюдения-переменные" в 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
Я бы использовал матрицы, так как они самые быстрые и простые в использовании, а затем создают набор перечислимых меток столбцов, чтобы упростить индексирование столбцов. Вот несколько способов сделать это:
Учитывая ваши имена переменных и предполагая, что они отображаются в порядке от столбцов от 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]);