【问题标题】:Insert one matrix into another every time an index is missing in a column每次列中缺少索引时将一个矩阵插入另一个矩阵
【发布时间】:2017-12-29 18:57:06
【问题描述】:

假设我有矩阵 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”列中存在非连续间隙,我想添加一个带有“-999s”的单独矩阵,并用适当的(即连续的)ID 号标记“id”列。请注意 ID 5 和 ID 8 之间如何存在两个间隙 - 理想情况下,我可以填写两次缺失值并相应地标记它们(例如,ID 6 和 ID 7)。

我尝试了以下代码,但没有成功。请注意,“数据”是一个类似于上面的矩阵 A 的矩阵。 'filler' 是一个 -999s 的 3x4 矩阵:

-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

【问题讨论】:

    标签: matlab matrix indexing


    【解决方案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);
    

    【讨论】:

      【解决方案2】:

      这里没有任何循环的解决方案(A是初始矩阵,B是结果)。目前假设 ID 值重复 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;
      

      【讨论】:

        【解决方案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
        

        【讨论】:

          【解决方案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
          

          【讨论】:

          • @PyjamaNinja 谢谢!但是,我是初学者:)
          猜你喜欢
          • 1970-01-01
          • 2021-06-30
          • 2012-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-17
          • 2015-06-16
          • 1970-01-01
          相关资源
          最近更新 更多