如何按列均匀分布矩阵中的数据?

How to evenly distribute data in a matrix by a column?

如果我有一个如下所示的矩阵:

X = [...
 1  2   3; 
 1  4   5; 
 1  6   7; 
 1  8   9; 
 0  10  11; 
 0  12  13; 
 1  14  15]

我想均匀地分布内容,所以我有这样的东西,其中第一列中的 0s 在整个数据集中相当均匀地分布,但行保持在一起:

Y = [...
 1  2   3; 
 1  4   5; 
 0  10  11; 
 1  6   7; 
 1  8   9;  
 0  12  13; 
 1  14  15]

(旁注这是一个虚构的示例,我使用的是更大的数据集)

均匀分布的意思是,如果我要分解数据集,无论我将数据集划分到哪里,我都希望 1 与 0 的比例相同。因此,如果前 5 行数据中有 4 个 1 和 1 个零,我希望在接下来的 10 行数据中有 8 个 1 和 2 个零。

如果只是想随机移动行,可以使用randperm:

Y = X(randperm(size(X, 1)), :)
Y =

     1     8     9
     0    12    13
     1    14    15
     1     4     5
     0    10    11
     1     2     3
     1     6     7

尽管如果行数很多,0 和 1 可以预期几乎均匀分布,但这并不能保证。

只有0和1的个数相等才能均匀分布。这样的话,就可以一一排列了:

X = [...
 1  2   3; 
 1  4   5; 
 0  6   7; 
 1  8   9; 
 0  10  11; 
 0  12  13; 
 1  14  15];
Y= zeros(size(X));
Y(1:2:end, :) = X(X(:, 1)==1, :);
Y(2:2:end, :) = X(X(:, 1)==0, :)
Y =

     1     2     3
     0     6     7
     1     4     5
     0    10    11
     1     8     9
     0    12    13
     1    14    15

但在你的情况下,0 和 1 的数量不相等,你可以结合以上方法。比如你的测试用例,先把两个1和两个0交替排列,然后把剩下的3个1随机分布(已经采取了相反的步骤实现):

Y = zeros(size(X));
I0 = find(~X(:, 1));
n0 = length(I0);
I1 = find(X(:, 1));
n1 = length(I1);
nRandom = abs(n0-n1);
nAlter = min(n0, n1);

filled = randperm(size(X, 1), nRandom);
if n0 > n1
   Y(filled, :) = X(I0(nAlter+1:end), :);
else
   Y(filled, :) = X(I1(nAlter+1:end), :);
end

empty = setdiff(1:size(X, 1), filled);
Y(empty(1:2:nAlter*2), :) = X(I1(1:nAlter), :);
Y(empty(2:2:nAlter*2), :) = X(I0(1:nAlter), :)

在数据子集的分布中强制执行某种均匀性的最简单方法是对行进行排序(请参阅 sortrows),然后通过交替行拆分数据。例如,分成 3 个相等的组:

X = sortrows(X);
X1 = X(1:3:end,:);
X2 = X(2:3:end,:);
X3 = X(3:3:end,:);

这确实会偏向日落:X1 的值总是小于 X2,等等