代码之家  ›  专栏  ›  技术社区  ›  Dev-iL

无插值网格化散乱数据

  •  2
  • Dev-iL  · 技术社区  · 6 年前

    我有三个向量, X Y ,和 Z ,表示矩阵中某些数据的三维坐标 V (即。 V = f(X,Y,Z) ). 以下是这些数据的一些特征(假设/断言,如果您愿意的话):

    • Z轴

      numel(X) == numel(Y);
      
    • 中唯一元素的数量 通常不同于 是的

    • 中的所有值 是独一无二的。

      numel(unique(Z)) == numel(Z);
      
    • [numel(X), numel(Z)] .

    在过去,我没有区分 ,我使用一个索引来引用它们,这样就可以很容易地绘制出具有“XY组合数”(即。 1:numel(X) )在一个轴上 Z轴 另一方面,使 结果很好。

    是的 另外,这就是为什么我想在三维可视化,使用混合的 scatter3 contourslice

    分散的部分很容易,因为我可以 repmat 是的 沿着它们的单子维度 numel(Z) Z轴 (使用 numel(X) ). 这将导致:

    Result of the scatter

    XX , YY , ZZ 直接使用 meshgrid :

    [ XX, YY, ZZ ] = meshgrid( unique(X), unique(Y), unique(Z) );
    

    VV .

    保持这样 VV型 应仅包含与原始数据集对应的点,其余空间应包含 NaN

    griddata interp3 执行插值,这将“填补洞”内的点云-这是 极不受欢迎 . 我认为索引可以用来填充 VV型

    我的问题是: 如何生成 不包含任何插值数据的 ?

    %% Generate some data:
    X = randi(10,100,1);
    Y = randi(15,100,1) - 5;
    Z = 1:50;
    V = X./Y.*Z;
    
    %% Scatter plot:
    nXY = numel(X); nZ = numel(Z);
    figure();
    scatter3( reshape( repmat(X,[1, nZ]),  [], 1), ...
              reshape( repmat(Y,[1, nZ]),  [], 1), ...
              reshape( repmat(Z,[nXY, 1]), [], 1), ...
              [], V(:), '.');
    
    %% Contours:
    % Create the 3d grid:
    [XX, YY, ZZ] = meshgrid( unique(X), unique(Y), unique(Z) );
    
    % Preallocate VV:
    VV = NaN(size(XX));
    
    % Populate VV: <--------------------------------------------- Help needed with this stage
    ind = randperm( numel(XX), numel(V) ); % PLACEHOLDER 
    VV(ind) = V;
    
    % Plot:
    hold on; contourslice(XX, YY, ZZ, VV, X(2), Y(3), Z(10) );
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Andras Deak -- Слава Україні    6 年前

    我相信有一种可能是过度的方法,将所有网格索引与所有线性数据点进行匹配。为此,我们需要注入一些维度来比较3d阵列 XX X 等元素:

    Xbc = reshape(X, [1,1,1,size(X)]);
    Ybc = reshape(Y, [1,1,1,size(Y)]);
    Zbc = reshape(Z, [1,1,1,size(Z)]);
    

    尺寸等 [N,M,K] (“bc”代表广播)。所以元素比较现在起作用了:

    match = reshape((XX == Xbc) & (YY == Ybc) & (ZZ == Zbc), [size(XX), numel(V)]);
    

    [N,M,K,P,Q] 如果 V 是大小 [P,Q] . 它包含了同样多的 true 如您所愿:

    >> sum(match(:)) == numel(V)
    
    ans =
    
      logical
    
       1
    

    所以现在我们需要沿着前三个维度挑选相应的索引,并将它们与

    [ii,jj,kk,ll] = ind2sub(size(match), find(match));
    

    现在左手边的所有数组都变大了 [numel(V), 1] 前三个给你指数 XX号 最后一个给出了

    V_inds = ll;
    VV_inds = sub2ind(size(VV), ii, jj, kk);
    
    VV(VV_inds) = V(V_inds);
    

    现在,由于某种原因,我在5000个指数中只看到了3750个独特指数:

    >> numel(VV_inds)           
    
    ans =
    
            5000
    
    >> numel(unique(VV_inds))
    
    ans =
    
            3750
    

    我似乎找不到任何其他原因,除了你的一些原始数据点重叠,由于重复的值 Y ,因此实际上无法在唯一点的三维网格中表示它们(因为某些三维点包含多个数据点)。我相信以下证明了这一点:

    >> size(unique([X,Y], 'rows'))
    
    ans =
    
        75     2
    
    >> size([X,Y])
    
    ans =
    
       100     2
    

    有100个 (x,y) 成对的,但只有75个独特的。不管你怎么把这些和正交结合起来 z


    我想我也得到了一个更有效的版本,使用 unique meshgrid 而不是 ndgrid 生成网格,以便生成的数组的尺寸(以及 VV 是的 ,和 Z 分别是。

    % take the indices
    [uX, ~, iX] = unique(X);
    [uY, ~, iY] = unique(Y);
    [uZ, ~, iZ] = unique(Z);
    
    % generate mesh and allocate result
    [XX, YY, ZZ] = ndgrid(uX, uY, uZ);
    VV = NaN(size(XX));
    
    % switch from `iX`, `iY` and `iZ` to a 2d mesh of size `[P,Q]` where `iX` and `iY` are of size `[P,1]` and `iZ` is of size `[Q,1`]:
    % a.k.a. lazy repmat
    iXbig = iX + 0*iZ.';
    iYbig = iY + 0*iZ.';
    iZbig = iZ.' + 0*iX;
    
    % turn 3d indices into linear index into VV
    VV_inds = sub2ind(size(VV), iXbig, iYbig, iZbig);
    
    % profit
    VV(VV_inds) = V;