1

我决定今晚有点疯狂,并与直方图箱一起对我正在分析的一些财务数据进行操作。

不过,派对似乎已经被大便了,因为我想应用我的“intra-bin”操作的方式并不明显,既不是通过研究也不是通过玩耍,而且证明很麻烦。

愿望:我想在列中使用“binning”索引来执行某种逐行的“intra-bin”操作,其中所述操作将对它自己的 bin 的第一个元素进行相对引用。请考虑下面的单箱示例,其中操作是取差值

一个=

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_difference_function(A) 提供一个具有任意数量 bin 的双列矩阵,这样如果

一个=

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_difference_function(A) 提供具有任意数量 bin 的双列矩阵,其中 bin 长度可能不是恒定的,如果

一个=

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 之间变化的许多 bin 进行操作。我认为在 accumarray 上玩可能会起到这样的作用

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基于方法可能需要大量资源,所以这里有一个基于 for-loop 的方法,它假设输入数据中的分类箱/ID -

[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

同样,假设已排序的 bin/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

好吧stackoverflow,我想通了!原来我是正确的关于使用 accumarray

矩阵 B、C 和 A 仅在函数内定义,以方便验证。矩阵 A 将按如下方式传递: best_bin_difference_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 回答