1

私は今晩少しワイルドになり、分析中のいくつかの財務データを操作するために、ヒストグラム ビンでパーティーをすることにしました。

しかし、私が「ビン内」操作を適用したい方法が、研究や遊びを通してもすぐに明らかにならず、煩わしいことを証明しているため、パーティーはうんざりしているようです.

欲望:列内で「ビニング」インデックスを使用して、ある種の行単位の「ビン内」操作を実行したいと思います。この操作では、独自のビンの最初の要素への相対参照が行われます。操作が違いを取る次の単一ビンの例を検討してください

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 の間で変化する多くのビンを操作するコードを作成することです。

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

fun(x) は for ループを持つ関数です。

Windows 7 で MATLAB 7.10.0.499 (R2010a) を実行しています。例によってこのクエリが長くなってしまい申し訳ありません。

4

2 に答える 2

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ベースのアプローチはリソースを大量に消費する可能性があるため、入力データでソートされたビン/ID を想定する for ループ ベースのアプローチを次に示します。

[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

繰り返しますが、ソートされたビン/ID を想定すると、これは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)]

この手法は、並べ替えられたデータを想定して一般化する他のすべてのアプローチに使用できます。

于 2014-09-01T04:12:29.903 に答える
1

よし、スタックオーバーフロー、わかった!accumarrayの使用については正しかったことがわかりました

行列 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 の応答の間でストレス テストを実行し、それに応じて賛成票を投じます。ご覧いただきありがとうございます!

于 2014-09-01T04:37:38.340 に答える