更快速地将数据分组到相同的四分位数范围内

时间:2014-04-03 06:27:41

标签: matlab statistics

考虑一个10 x 10矩阵K的列,比如K(:,1)

我想创建一个10x4二进制矩阵,告诉我们行条目属于哪个四分之一范围。例如

   ith row of binary matirx : [ 1 0 0 0 ] => K(i,1)<prctile(K(:,1),25)

我的代码:

   %%%

   K = randi(10,10);
   BINMAT = zeros(size(K,1),4);

   y_1 = prctile(K(:,1),25) ; 
   ID_1 = find(K(:,1) < y_1);
   BINMAT(ID_1,1)=1;

   y_2 = prctile(K(:,1),50);
   ID_2 = find(( K(:,1) > y_1 &  K(:,1) < y_2 ));
   BINMAT(ID_2,2)=1;

   y_3 = prctile(K(:,1),75);
   ID_3 = find(( K(:,1) > y_2 & K(:,1) < y_3 ));
   BINMAT(ID_3,3)=1;

   y_4 = prctile(K(:,1),100);
   ID_4 = find((K(:,1) > y_3 & K(:,1) < y_4 ));
   BINMAT(ID_4,4)=1;
   %%%

如果我不仅要为一列而是为一组列执行此操作,请说A = [1 2 5 6],BINMAT应该有16列(每列K为4)。有更快的速度这样做的方法?

3 个答案:

答案 0 :(得分:0)

您可以使用for循环来迭代A

给出的所需列索引
K = randi(10,10);
A = [1 2 5 6]; % columns in K to process
BINMAT = zeros(size(K,1), 4*length(A));

cnt = 0; % helper
for col_indx = A
    y_1 = prctile(K(:,col_indx),25) ;
    ID_1 = find(K(:,col_indx) < y_1);
    BINMAT(ID_1, 4*cnt + 1) = 1;

    y_2 = prctile(K(:,col_indx),50);
    ID_2 = find(( K(:,col_indx) > y_1 &  K(:,col_indx) < y_2 ));
    BINMAT(ID_2, 4*cnt + 2)=1;

    y_3 = prctile(K(:,col_indx),75);
    ID_3 = find(( K(:,col_indx) > y_2 & K(:,col_indx) < y_3 ));
    BINMAT(ID_3, 4*cnt + 3)=1;

    y_4 = prctile(K(:,col_indx),100);
    ID_4 = find((K(:,col_indx) > y_3 & K(:,col_indx) < y_4 ));
    BINMAT(ID_4, 4*cnt + 4)=1;

    cnt = cnt + 1;
end

我注意到BINMAT的许多行只包含零,因为您发布的代码的值不等于y_1y_2y_3和{考虑到{1}}。我认为你应该使用y_4等等。

答案 1 :(得分:0)

另一个建议:

K = randi(10,10)
p = 25:25:100;
Y = prctile(K, p);
Y = [zeros(1, size(Y, 2)) ;Y];
BINMAT = zeros(size(K, 1), length(p), size(K, 2));

for j = 1:size(K, 2)
    for i = 1:length(p)
    BINMAT(Y(i, j) <= K(:,j) & K(:, j) <= Y(i+1, j), i, j) = 1;
    end
end

然后,BINMAT(:, :, i)是您为K(:, i)定义的二进制矩阵。

答案 2 :(得分:0)

Percentile的核心是排序列表中元素的位置。因此,直接使用sort将提供最有效的解决方案,因为您需要多列中的多个百分位数。

首先,我们需要一种方法将固定箱分配给已排序的位置。这是我认为prctile使用的向量,但是由于10不能均匀地分成4个区域,所以它有点武断。 (换句话说,你将元素3分配给0-25%的bin或25%-50%的bin)? floor(4*(0.5+(0:9).')/10)+1

现在我们只需要对每列进行排序,并将每个原始元素的排序位置分配给其中一个位置。排序的第二个输出完成了大部分工作:

K = randi(10,10);
A = [1 2 5 6]; % columns in K to process
BINMAT = zeros(size(K,1), 4*length(A));
bins = floor(4*(0.5+(0:9).')/10)+1;

[sortedK, idx] = sort(K(:,A));

% The k'th element of idx belongs to the c(k) bin.  So now generate the output.
% We need to offset to the correct block of BINMAT for each column
offset_bins = bsxfun(@plus, bins, 4*(0:length(A)-1));
BINMAT(sub2ind(size(BINMAT), idx, offset_bins)) = 1;