2015-08-24 22 views
6

accumarray belirtilen fonksiyonu tarafından atanan değere sahip geçerli bir göstergesi çiftlerinin yere elemanları ile bir matris oluşturmak için endeksler iki sıra kullanan bir tablo, örneğin:accumarray izin verme çıkışı

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

Bu şekilde datamatrix olacak Değerleri olan bir 20x20 matrisi. Bununla birlikte, A ve B değerleri çok büyükse, bu, çok uzak bir matrisle sonuçlanacak ve uzak köşede küçük bir veri kümesi olacaktır. bunu aşmak için, bir accumarrayissparse ayarlı olabilir:

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

Bu durumda min(A) içinde çok fazla bellek kazandıracak ve/veya min(B)/çok büyüktür.

Benim sorunum, ancak, hangi İlk iki sütunda endeksleme dayalı sütunlar yedi ayrı üç araçlarını ve esaslı üçüncü sütunda standart sapmasını toplamak istediğiniz, M~1e8 ile, bir Mx7 matris olması yanı üçte üzerine:

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

Ben X ve Y endeksleri nerede, Z o pikselin ortalama yüksekliği, R, G, B ve olduğu [X Y Z std R G B I] olarak yapılandırılmış, geri tabloya kaydetmek istiyor I, piksel başına ortalama değerler (renk ve yoğunluk) ve std, yüksekliklerin standart sapmasıdır (ör. pürüzlülük). Bu durumda issparse kullanarak, repmat kullanarak accumarray kaynaklanan matrices dönüştürmek beri yardımcı olmaz.

Bu kodun amacı, bir nokta bulutundan bir toprak parçasının yüksekliğini, pürüzlülüğünü, rengini ve yoğunluğunu tahmin etmektir. Bir ızgara oluşturmak için X ve Y koordinatlarını yuvarlattım ve şimdi grid hücresi başına bu ortalama değerlere gereksinim duyuyorum, ancak bir "tablo" olarak çıktı (MATLAB veri türü değil, varsayılan matris çıktısı olan bir 2D dizisi).

Yani, soru ile sonuçlandırmak için:

accumarray için bir yol veya çıkış benzer bir işlev ara madde (potansiyel olarak çok büyük) matris olmadan bu tablo var mı? Aşağıda

Kodu:

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),:); 

burada dokuzuncu sütun hücre başına noktalarının sadece miktarıdır.

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 

aynı X, Y, böylece tüm noktalar (örneğin [19 36] veya [21 37]) ortalaması alınır (yükseklik, RGB, bu sırayla yoğunluk) ve üçüncü sütunda değerlerinin standart sapma da arzu edilir:

Diğer veriler için

ve benzeri.

Kodumu sahip olduğum son sürüme güncelledim. Bu küçültülmüş bellek yükü oldukça fazladır, çünkü işlev şimdi aynı anda ızgaraları bir kereliğine değil de arka arkaya oluşturur. Bununla birlikte, kod paralel olarak çalışmaktadır, bu yüzden hala sekiz eşzamanlı ızgara oluşturulmuştur, böylece bir çözüm hala takdir edilecektir.

+1

Takip ettiğimden emin değilim. Eğer 'accumarray' gibi yapmak istiyorsanız ama sayıları yerine _rows_' toplamak istiyorsanız, [bu Q & A] 'da olduğu gibi (seyrek) matris çarpımını kullanabilirsiniz (http://stackoverflow.com/questions/29906059/summing-rows-by- index-using-accumarray) –

+0

Sparse() kullanamıyorum çünkü yerel "toplamı" ndan başka işlevleri desteklemiyor ve tutam tükenmez bir matris ile sonuçlanamıyor çünkü repmat sparseslerle çalışmaz. – Adriaan

+1

İstediğiniz şeyin _can_'ın seyrek matris çarpımı ile yapılması gerektiğini hissediyorum. Ama giriş ve istenen çıkış ile minimal, çalışan bir örnek oluşturmanız gerekir; Sorunuz olduğu gibi çok net değil –

cevap

3

doğrusal endeksleri kullanılarak çözüm ve 2D seyrek matrisin Şimdi

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); 

Eğer

inter = [Originaldata(:,1), Originaldata(:,2), full(daccum(:,lind))' ]; 
1

Yapabilirsin öncesi süreç verileri gerekenleri tek alabilirsiniz taslağı.

%// 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,:); 
2

yapabilirsiniz ilk kullanımı: Eğer 0 standart sapma ile uğraşmak zorunda kalmamak için bu şekilde elde edebilirsiniz

bir şey (örneğin iki ya da daha az olaylar sahip olanlar gibi) istenmeyen çizgileri kaldırmak olduğunu unique, 'rows' ile X ve Y koordinatlarının benzersiz çiftlerinin indislerini bulmak için, daha sonra bu indeksleri accumarray numarasına çağrılarınızdaki alt simge olarak kullanmalısınız (yapmadığı için her sütun için ayrı ayrı çağırmanız gerekir) t matris girişlerini kullan):

[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)]; 
İlgili konular