6

accumarray2 行のインデックスを使用して、指定された関数によって割り当てられた値を持つ有効なインデックス ペアの位置に要素を持つ行列を作成します。たとえば、次のようになります。

A = [11:20]; 
B = flipud([11:20]); 
C = 1:10;
datamatrix = accumarray([A B],C);

この方法datamatrix20x20、値を持つマトリックスになります。Aただし、との値Bが非常に大きい場合、ほとんどが空の行列になり、端の隅に小さなデータのバッチができます。これを回避するには、次のように設定accumarrayissparseます。

sparsedatamatrix = accumarray([A B],C,[],@sum,[],true);

min(A)これにより、非常に大きい場合や非常に大きい場合に、多くのメモリが節約されますmin(B)

しかし、私の問題は、最初の 2 列のインデックスに基づいて列 3 から 7 の平均を収集し、3 番目の列に基づいて 3 番目の列の標準偏差を収集したいのMx7行列があることです。M~1e8

result = accumarray([data(:,1) data(:,2)],data(:,3),[],@std);

これを次のように構造化されたテーブルに保存したいと思います[X Y Z std R G B I]。 ここで、XYはインデックス、Zはそのピクセルの平均高さ、 、 はRピクセルGあたりの平均値 (色と強度)、Bは高さの標準偏差 (つまり、粗さ)。を使用して得られた行列を変換するため、この場合に を使用しても役に立ちません。Istdissparseaccumarrayrepmat

このコードのポイントは、点群から土地の高さ、粗さ、色、強度を推定することです。X と Y の座標を丸めてグリッドを作成し、グリッド セルごとにこれらの平均値が必要になりましたが、「テーブル」として出力します (MATLAB データ型ではなく、既定のマトリックス出力ではない 2D 配列)。

したがって、質問を締めくくるには:

accumarray中間の(潜在的に非常に大きな)マトリックスなしでこのテーブルを出力する方法または同様の関数はありますか?

以下のコード:

Xmax = max(Originaldata(:,1));
Ymax = max(Originaldata(:,2));
X_avg_grid=(Edgelength:Edgelength:Xmax*Edgelength)+Xorig;
TestSet = zeros(Xmax*Ymax,9);

xx = [1:length(X_avg_grid)]'; %#ok<*NBRAK>
TestSet(:,1) = repmat(xx,Ymax,1);
ll = 0:Xmax:Xmax*Ymax;
for jj = 1:Ymax
    TestSet(ll(jj)+1:ll(jj+1),2) = jj;
end

for ll = 1:7
    if ll == 2
        tempdat = accumarray([Originaldata(:,1) Originaldata(:,2)],Originaldata(:,3),[],@std);
        tempdat = reshape(tempdat,[],1);
        TestSet(:,ll+2) = tempdat;
    elseif ll == 7
        tempdat = accumarray([Originaldata(:,1) Originaldata(:,2)],1);
        tempdat = reshape(tempdat,[],1);
        TestSet(:,ll+2) = tempdat;
    elseif ll == 1
        tempdat = accumarray([Originaldata(:,1) Originaldata(:,2)],Originaldata(:,3),[],@mean);
        tempdat = reshape(tempdat,[],1);
        TestSet(:,ll+2) = tempdat;
    else
        tempdat = accumarray([Originaldata(:,1) Originaldata(:,2)],Originaldata(:,ll+1),[],@mean);
        tempdat = reshape(tempdat,[],1);
        TestSet(:,ll+2) = tempdat;
    end
end

TestSet = TestSet(~(TestSet(:,9)==0),:);

ここの 9 列目は、セルあたりのポイント数です。

Originaldata = 
19  36  2.20500360107422    31488   31488   31488   31611
20  37  2.26400360107422    33792   33792   34304   33924
20  37  2.20000360107422    33536   33536   34048   33667
19  36  2.20500360107422    34560   34560   34560   34695
20  36  2.23300360107422    32512   32512   33024   32639
21  38  2.22000360107422    31744   31488   33024   31611
21  37  2.20400360107422    32512   32768   33792   32896
21  37  2.24800360107422    29696   29440   30720   29555
21  38  2.34800360107422    32768   32768   32768   32639
21  37  2.23000360107422    33024   33024   33536   33153

したがって、同じ X、Y (例:[19 36]または[21 37]) 上のすべてのポイントが平均化され (高さ、RGB、強度の順で)、3 番目の列の値の標準偏差も求められます。

Result = 
19  36  2.2050036   0.00        33024   33024   33024       33153
21  37  2.227336934 0.02212088  31744   31744   32682.66    31868

残りのデータについても同様です。

コードを最新バージョンに更新しました。これにより、関数がグリッドを一度に作成するのではなく、次々に作成するようになったため、メモリのオーバーヘッドが大幅に削減されました。ただし、コードは並行して実行されているため、まだ 8 つの同時グリッドが作成されているため、解決策があれば幸いです。

4

3 に答える 3

3

線形インデックスと 2D 疎行列を使用したソリューションのスケッチ

lind = Originaldata(:,1) + max( Originaldata(:,1) ) * ( Originaldata(:,2) - 1 );
daccum(7,:) = accumarray( lind, 1, [], @sum, [], true ); %// start with last one to pre-allocate all daccum
daccum(1,:) = accumarray( lind, Originaldata(:,3), [], @mean, [], true );
daccum(2,:) = accumarray( lind, Originaldata(:,3), [], @std, [], true );
daccum(3,:) = accumarray( lind, Originaldata(:,4), [], @mean, [], true );
daccum(4,:) = accumarray( lind, Originaldata(:,5), [], @mean, [], true );
daccum(5,:) = accumarray( lind, Originaldata(:,6), [], @mean, [], true );
daccum(6,:) = accumarray( lind, Originaldata(:,7), [], @mean, [], true );

必要なものだけを手に入れることができるようになりました

inter = [Originaldata(:,1), Originaldata(:,2), full( daccum(:,lind) )' ];
于 2015-08-24T14:37:15.980 に答える
2

最初に、X 座標と Y 座標の一意のペアのインデックスを検索するオプションを使用uniqueして、代わりにこれらのインデックスを呼び出しの添え字入力として使用できます (列ごとに個別に呼び出す必要があります。 t は行列入力を処理します):'rows'accumarrayaccumarray

[xyPairs, ~, index] = unique(Originaldata(:, 1:2), 'rows');
nPairs = max(index);
Result = [xyPairs ...
          accumarray(index, Originaldata(:, 3), [nPairs 1], @mean) ...
          accumarray(index, Originaldata(:, 3), [nPairs 1], @std) ...
          accumarray(index, Originaldata(:, 4), [nPairs 1], @mean) ...
          accumarray(index, Originaldata(:, 5), [nPairs 1], @mean) ...
          accumarray(index, Originaldata(:, 6), [nPairs 1], @mean) ...
          accumarray(index, Originaldata(:, 7), [nPairs 1], @mean) ...
          accumarray(index, ones(size(index)), [nPairs 1], @sum)];
于 2017-04-20T16:30:39.320 に答える
1

データを前処理できます。

この方法で実現できることの 1 つは、不要な行 (出現回数が 2 回以下の行など) を削除して、0標準偏差に対処する必要がないようにすることです。

%// Count occurences:
combined_coord = Originaldata(:,1)*1E6+Originaldata(:,2); %// "concatenating" the coords
[C,~,ic] = unique(combined_coord);
occurences = [C accumarray(ic,1)];
%// Find all points that have <=2 occurences:
coords_to_remove = occurences((occurences(:,2)<=2),1);
%// Find valid lines:
valid_lns = ~sum(bsxfun(@eq,combined_coord,coords_to_remove'),2); %'
%// Filter original data:
new_data = Originaldata(valid_lns,:);
于 2015-10-31T15:52:12.497 に答える