Хобрук: Ваш путь к мастерству в программировании

Вставлять одну матрицу в другую каждый раз, когда в столбце отсутствует индекс

Допустим, у меня есть матрица A:

A = [... %ID  Time   X
    1   0    0.7
    1   1    0.1
    1   2   -0.5
    1   3   -1.6
    3   0    0.3
    3   1    0.2
    3   2    0.0
    3   3   -0.2
    4   0    0.7
    4   1   -0.1
    4   2   -0.3
    4   3    0.2
    5   0   -0.5
    5   1   -0.4
    5   2   -0.9
    5   3   -0.4
    8   0    0.5
    8   1    1.0
    8   2    0.3
    8   3    0.4
    ];

Как вы получите что-то вроде этого (например, Матрица B):

ID  Time      X
1     0      0.7
1     1      0.1
1     2     -0.5
1     3     -1.6
2   -999    -999
2   -999    -999
2   -999    -999
2   -999    -999
3     0      0.3
3     1      0.2
3     2      0.0
3     3     -0.2
4     0      0.7
4     1     -0.1
4     2     -0.3
4     3      0.2
5     0     -0.5
5     1     -0.4
5     2     -0.9
5     3     -0.4
6   -999    -999
6   -999    -999
6   -999    -999
6   -999    -999
7   -999    -999
7   -999    -999
7   -999    -999
7   -999    -999
8     0      0.5
8     1      1.0
8     2      0.3
8     3      0.4

Каждый раз, когда в столбце «id» есть непоследовательный пробел, я хочу добавить отдельную матрицу с «-999» и пометить столбец «id» соответствующим (т.е. последовательным) идентификационным номером. Обратите внимание, что между ID 5 и ID 8 есть два пробела — в идеале я мог бы заполнить пропущенные значения дважды и соответствующим образом их пометить (например, ID 6 и ID 7).

Я пробовал следующий код, но безуспешно. Обратите внимание, что «данные» — это матрица, подобная матрице A выше. «наполнитель» представляет собой матрицу 3x4 из -999:

-999 -999 -999
-999 -999 -999
-999 -999 -999
-999 -999 -999

Образец кода:

ii = 1; %Starting counter
kk = ii+4; %So I don't start by indexing a row which doesn't yet exist

for ii = 1:4:length(data);
    if data(kk,1) ~= data(kk-4,1) + 1; %If there's a gap between the ID values greater than 1, i.e. they are non-consecutive
        data = [data(1:kk-1, :); filler; data(kk:end, :)]; %Append the filler column to the part of the matrix where another ID should be
    elseif data(kk,1) == -999; 
        end
end
29.12.2017

Ответы:


1

Классическое задание для accumarray:

fillval = -999;
A = [...
    1   0    0.7
    1   1    0.1
    1   2   -0.5
    1   3   -1.6
    3   0    0.3
    3   1    0.2
    3   2    0.0
    3   3   -0.2
    4   0    0.7
    4   1   -0.1
    4   2   -0.3
    4   3    0.2
    5   0   -0.5
    5   1   -0.4
    5   2   -0.9
    5   3   -0.4
    8   0    0.5
    8   1    1.0
    8   2    0.3
    8   3    0.4
    ];

%// Compact solution
X = accumarray(A(:,1),(1:size(A,1)).',[],@(x) {A(x,:)});
X(cellfun(@isempty,X)) = {fillval*ones(size(X{1}))};
out = cell2mat(X);

Объяснение:

% indices of groups
gidx = A(:,1);
% vector of all indices
N = 1:size(A,1);  
% create groups with accumarray
X = accumarray(gidx(:),N(:),[],@(x) {A(x,:)});
% create logical vector for missing indices
mask = cellfun(@isempty,X);
% form fill matrix with same size as single group
fillmat = fillval*ones(size(X{1}));
% expand A to complete matrix with fill values
X(mask) = {fillmat};
% transform cell array to double array
out = cell2mat(X);
30.12.2017

2

Здесь решение без каких-либо циклов (Aисходная матрица, B результат). В настоящее время предполагается, что значение идентификатора повторяется 4 раза и что в столбце 2. у вас есть значения 0:3 . Не уверен, что это быстрее, чем решение Tommasos, потому что ismember может занять много времени для очень больших матриц.

% create template B to fill in values
B = [repelem(A(1,1):A(end,1),1,4).' repmat(0:3,1,A(end,1)-A(1,1)+1).' repmat(-999,(A(end,1)-A(1,1)+1)*4,1)];

% copy values from column 3 of A to column 3 of B where the first 2 columns are the same
[~,loc] = ismember(A(:,1:2),B(:,1:2),'rows');
B(loc,3) = A(:,3);

% Where column 3 == -999, also set column 2 to -999
B(B(:,3)==-999,2)=-999;
30.12.2017

3

Предлагаю вам следующее решение, в котором я постарался максимально векторизовать процесс:

A = [
    1   0    0.7
    1   1    0.1
    1   2   -0.5
    1   3   -1.6
    3   0    0.3
    3   1    0.2
    3   2    0.0
    3   3   -0.2
    4   0    0.7
    4   1   -0.1
    4   2   -0.3
    4   3    0.2
    5   0   -0.5
    5   1   -0.4
    5   2   -0.9
    5   3   -0.4
    8   0    0.5
    8   1    1.0
    8   2    0.3
    8   3    0.4
 ];

A_min = min(A(:,1));
A_max = max(A(:,1));
A_seq = A_min:A_max;
A_seq_cnt = numel(A_seq) * 4;

B_idx1 = repmat(A_seq,4,1);
B = [B_idx1(:) repmat((ones(A_seq_cnt,1) * -999),1,2)];

for n = unique(A(:,1)).'
    B((B(:,1) == n),2:3) = A((A(:,1) == n),2:3);
end

Результат:

B =

 1     0   0.7
 1     1   0.1
 1     2  -0.5
 1     3  -1.6
 2  -999  -999
 2  -999  -999
 2  -999  -999
 2  -999  -999
 3     0   0.3
 3     1   0.2
 3     2     0
 3     3  -0.2
 4     0   0.7
 4     1  -0.1
 4     2  -0.3
 4     3   0.2
 5     0  -0.5
 5     1  -0.4
 5     2  -0.9
 5     3  -0.4
 6  -999  -999
 6  -999  -999
 6  -999  -999
 6  -999  -999
 7  -999  -999
 7  -999  -999
 7  -999  -999
 7  -999  -999
 8     0   0.5
 8     1     1
 8     2   0.3
 8     3   0.4
29.12.2017

4

Вы можете исправить это следующим образом:

result = zeros(4*max(data(:,1)),3); % initialization
last_idx = 1; % counter from 1 to max
idx = 1;
len = length(data(:,1));
while(idx < len)
    range = (4*(last_idx-1)+1):(4*last_idx);
    if data(idx,1) ~= last_idx % find missed index
        result(range,:) = repmat([last_idx -9 -9],4,1);
    else
        result(range,:) = data(idx:idx+3,:);
        idx = idx + 4;
    end
    last_idx = last_idx + 1;
end
29.12.2017
  • @PyjamaNinja Спасибо! Но я новичок :) 30.12.2017
  • Новые материалы

    React on Rails
    Основное приложение Reverb - это всеми любимый монолит Rails. Он отлично обслуживает наш API и уровень просмотра трафика. По мере роста мы добавляли больше интерактивных элементов..

    Что такое гибкие методологии разработки программного обеспечения
    Что представляют собой гибкие методологии разработки программного обеспечения в 2023 году Agile-методологии разработки программного обеспечения заключаются в следующем: И. Введение A...

    Ториго  — революция в игре Го
    Наш следующий вызов против ИИ и для ИИ. Сможет ли он победить людей в обновленной игре Го? Обратите внимание, что в следующей статье AI означает искусственный интеллект, а Goban  —..

    Простое развертывание моделей с помощью Mlflow — Упаковка классификатора обзоров продуктов NLP от HuggingFace
    Как сохранить свои модели машинного обучения в формате с открытым исходным кодом с помощью MLFlow, чтобы позже получить возможность легкого развертывания. Сегодня модели упаковки имеют несколько..

    Математика и интуиция - Часть 1
    У каждой математической формулы есть доказательство. Часто эти доказательства слишком сложно понять, поскольку многие из них основаны на индукции, некоторые - на очень сложных наблюдениях, а..

    Раскрытие возможностей НЛП: часть речевой маркировки и ее проблемы
    В сфере обработки естественного языка (NLP) маркировка частей речи (POS) выступает в качестве фундаментального метода, позволяющего компьютерам понимать и анализировать человеческий язык на..

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