2014-09-01 22 views
1

我決定今天晚上有點野外派對和直方圖箱來操作我分析的一些財務數據。但是,由於我想通過研究或玩耍,並且證明令人煩惱,所以我想要應用我的「箱內」操作的方式並不是顯而易見的,但似乎黨已經被拖垮了。花式分箱操作 - 如何矢量化相對的箱內操作?

慾望:我想在列中使用'binning'索引來執行某種行內'bin'操作,其中所述操作將對其自己的bin的第一個元素進行相對引用。請考慮以下的單倉示例,其中操作是採取差

A =

1 10.4 
1 10.6 
1 10.3 
1 10.2 

相對操作將需要第2列中的所有元素和第2列,使得所述第一元件之間的差

bin_differencing_function(A) =

1 10.4 0.0 
1 10.6 0.2 
1 10.3 -0.1 
1 10.2 -0.2 

現在,更方便的將是能夠養活bin_differencing_function (A)的雙列矩陣與倉的任意數量,使得如果

A =

1 10.4 
1 10.6 
1 10.3 
1 10.2 
2 10.2 
2 10.6 
2 10.8 
2 10.8 
3 11.0 
3 10.8 
3 10.8 
3 10.8 

better_bin_differencing_function(A) =

1 10.4 0.0 
1 10.6 0.2 
1 10.3 -0.1 
1 10.2 -0.2 
2 10.2 0.0 
2 10.6 0.4 
2 10.8 0.6 
2 10.8 0.6 
3 11.0 0.0 
3 10.8 -0.2 
3 10.8 -0.2 
3 10.8 -0.2 

最方便的。將能夠養活better_bin_differencing_function(A )具有任意數量的分箱的雙列矩陣,其中分箱長度可以不是恆定的,使得如果

A =

1 10.4 
1 10.6 
1 10.3 
2 10.2 
2 10.6 
2 10.8 
2 10.8 
2 10.7 
3 11.0 
3 10.8 

best_bin_differencing_function(A) =

1 10.4 0.0 
1 10.6 0.2 
1 10.3 -0.1 
2 10.2 0.0 
2 10.6 0.4 
2 10.8 0.6 
2 10.8 0.6 
2 10.7 0.5 
3 11.0 0.0 
3 10.8 -0.2 

最大的願望是創建一段代碼,利用量化的(如果可能的話)對許多垃圾箱誰的長度將介於1和200我改變操作m認爲準確的玩法可能會這樣做:

accumarray(A(:,1),A(:,2),[],@(x) fun(x)) 

其中fun(x)是一個帶for循環的函數。

我在Windows 7上運行MATLAB 7.10.0.499(R2010a)。對不起,這個例子使這個查詢很長。

+0

我的直覺是,一個for循環結合bsxfun將是一個快速解決方案... – bla 2014-09-01 03:40:34

回答

1

方法#1

這裏有一個bsxfun爲基礎的方法 -

%// Get the first column IDs from A and positions of the elements from 
%// each ID/bin 
[A_id,first_idx] = unique(A(:,1)) 

%// First elements from each ID/bin 
first_ele = A(first_idx,2) 

%// Get a 2D logical array s.t. the ones in each column represent the 
%// presence of all element corresponding to each ID/bin 
match_ind = bsxfun(@eq,A(:,1),A_id') %//' 

%// Create the base matrix with the logical array, s.t. the ones are 
%// replaced by the actual elements 
base_mat = bsxfun(@times,match_ind,first_ele.') %//' 

%// Final accumulate all the elements and subtract from the second column 
%//of A to form the new new column for the output 
out = [A A(:,2) - base_mat(match_ind)] 

方法2

bsxfun爲基礎的方法可能是消耗資源,所以這裏是一個基於for循環的假設分類箱/ I DS輸入數據 -

[A_id,first_idx] = unique(A(:,1)); 
[A_id,last_idx] = unique(A(:,1),'last'); 
out = [A A(:,2)]; 
for k1 = 1:numel(first_idx) 
    first_id = first_idx(k1); 
    last_id = last_idx(k1); 
    out(first_id:last_id,3) = out(first_id:last_id,3) - out(first_id,3); 
end 

方法3

這可能是一個有趣的方法來測試過 -

[~,first_id] = max(bsxfun(@eq,A(:,1),A(:,1)')) %//' 
out = [A A(:,2) - A(first_id,2)] 

方法#4

再次,假設分類垃圾箱/ IDS,這是一個diff + cumsum基礎的做法,似乎是最快給出的假設成立 -

first_match = [1; diff(A(:,1))] 
first_match(first_match==1) = [1 ; diff(find(first_match))] 
out = [A A(:,2) - A(cumsum(first_match),2)] 

請注意,如果它們沒有排序,你可以使用sortrows如下所示 -

[A,sorted_ind] = sortrows(A,1) 
first_match = [1; diff(A(:,1))] 
first_match(first_match==1) = [1 ; diff(find(first_match))] 
out(sorted_ind,:) = [A A(:,2) - A(cumsum(first_match),2)] 

您可以使用這種技術,它假定排序的數據,使這些廣義的所有其他方法。

+0

神聖的鯖魚!感謝所有關注@Divakar。我會很快測試這些,但在所有的方法同時+1!謝謝! – zelusp 2014-09-01 18:05:08

+0

@zelusp對此有何更新? :)我認爲你可以跳進方法#4,這在我的快速測試中似乎是最快的。 – Divakar 2014-09-03 10:44:10

+0

剛剛完成創建此Fancy Binning操作的調用例程。執行時間平均值:我的解決方案= 0.00950秒,方法4 = 0.00017秒...執行時間減少了98%。你規則@Divakar!謝謝你,你的回答非常幫助我! – zelusp 2014-09-04 01:29:04

1

好吧stackoverflow,我想通了!原來,我對於使用準確測試是正確的

矩陣B,C和A只在函數內定義以便驗證。矩陣A將被傳遞如下:best_bin_differencing_function(A)

function differenced_bins=best_bin_differencing_function() 
B=[1 1 1 2 2 2 2 2 3 3]'; 
C=[10.4 10.6 10.3 10.2 10.6 10.8 10.8 10.7 11.0 10.8]'; 
A=[B,C]; 
differenced_bins=cell2mat(accumarray(A(:,1),A(:,2),[],@(x) {fun(x)})); 
end 

function y=fun(var) 
    y=zeros(length(var),1); 
    for i=1:length(var) 
     y(i)=var(i)-var(1); 
    end 
end 

我要運行這個和Divakar的響應之間@壓力測試和意志贊成票相應。謝謝大家看看!

+0

使用'cell-arrays'實際上可能會變慢。看看你是否可以找出'accumarray'來代替數字數組。雖然好努力! +1 – Divakar 2014-09-01 04:40:34

+0

有趣的是,謝謝@Divakar。我會看一看 – zelusp 2014-09-01 04:46:44