Select 来自 table 的聚集行
Select clustered rows from a table
我会尝试将我的问题写在列表中以便于理解:
- 我有一个大小为
1000x30
的 matlab table T
。
- table 中最后一列名为 'Class' 的所有数据都具有特定的整数值,范围从
1
到 20
。
- 所以有些行的值为
1
,这意味着这些行属于 "Class1",有些行的值为 2
,有些行的值为 20
等等。
- 某class的行数不等于行数
有另一个 class 的行,所以可能有 100 行有 class
1
但 10 行有 class 2
和 500 有 class 3
等等。
这就是我想要做的:
- 我想得到具有最小值的 class 的行数
分配给它的行数。因此,假设 Class
10
分配给 count == 3
的行最少,而其余 classes 分配给它们的行超过 3 行。
- 然后我将有一个名为
YesNo
的新列,其中只有值 0
或 1
。
- 然后 class 中计数最少的所有行(例如本例中的 Class 10)的值将是
1
.
- 对于所有其他 classes 的其余行,我想从其他 class 中随机 select 与 class 相似的行数最低数字(在本例中为
3
)。
- 然后对于这些随机 selected 行彼此 class 新列中的值
YesNo
将是 1
而对于其余未选择行数将为 0。
- 所以在这个例子中,这将以一个具有
1000
值的新列结束,其中 3*20 个将具有 1(3-> 分配给 class 的行数最低计数,20-> 是 classes 的数量),其余为 0。
我想知道如何在 MATLAB R2015b 中完成此操作?我知道我可以使用 T.YesNo = newArr;
在 table 中创建一个新列,其中 newArr
是具有 0
和 1
值的 1000x1 double
。
作为一个小例子,如果 T
是 10x3
并且只有 3 个 classes (1,2,3
),下面是 T
的样子:
ID Name Class
0 'a' 3
1 'b' 2
2 'a' 2
3 'b' 2
4 'a' 3
5 'a' 1
6 'a' 1
7 'b' 2
8 'b' 1
9 'a' 2
因此,如上所示,Class3 是计数最少的,只有 2 行。所以我想随机 select 两行 Class1 和 Class2 然后将这些随机 selected 行的新列的值设置为 1
而其余的将是 0
,如下所示:
ID Name Class YesNo
0 'a' 3 1
1 'b' 2 0
2 'a' 2 1
3 'b' 2 0
4 'a' 3 1
5 'a' 1 0
6 'a' 1 1
7 'b' 2 0
8 'b' 1 1
9 'a' 2 1
见下面的代码。它应该是不言自明的。如果有什么不清楚 - 请询问。
function q42944288
%% Definitions
MAX_CLASS = 20;
%% Setup
tmp = struct;
tmp.Data = rand(1000,1);
tmp.Class = uint8(randi(MAX_CLASS,1000,1)); % uint8 for efficiency
T = table(tmp.Data,tmp.Class,'VariableNames',{'Data','Class'});
%% Solution:
% Step 1:
[count,minVal] = min(histcounts(T.Class,'BinMethod','integers'));
% Steps 2+3:
T.YesNo = T.Class == minVal;
% Steps 4+5+6:
whichClass = bsxfun(@eq,T.Class,1:MAX_CLASS); % >=R2007a syntax
% whichClass = T.Class == 1:MAX_CLASS; % This is a logical array, >=R2016b syntax.
for indC = setdiff(1:MAX_CLASS,minVal)
inds = find(whichClass(:,indC));
T.YesNo(inds(randperm(numel(inds),count))) = true;
end
%% Test:
fprintf(1,'\nThe total number of classes is %d', numel(unique(T.Class)));
fprintf(1,'\nThe minimal count is %d',count);
fprintf(1,'\nThe total number of 1''s in T.YesNo is %d', sum(T.YesNo));
我会尝试将我的问题写在列表中以便于理解:
- 我有一个大小为
1000x30
的 matlab tableT
。 - table 中最后一列名为 'Class' 的所有数据都具有特定的整数值,范围从
1
到20
。 - 所以有些行的值为
1
,这意味着这些行属于 "Class1",有些行的值为2
,有些行的值为20
等等。 - 某class的行数不等于行数
有另一个 class 的行,所以可能有 100 行有 class
1
但 10 行有 class2
和 500 有 class3
等等。
这就是我想要做的:
- 我想得到具有最小值的 class 的行数
分配给它的行数。因此,假设 Class
10
分配给count == 3
的行最少,而其余 classes 分配给它们的行超过 3 行。 - 然后我将有一个名为
YesNo
的新列,其中只有值0
或1
。 - 然后 class 中计数最少的所有行(例如本例中的 Class 10)的值将是
1
. - 对于所有其他 classes 的其余行,我想从其他 class 中随机 select 与 class 相似的行数最低数字(在本例中为
3
)。 - 然后对于这些随机 selected 行彼此 class 新列中的值
YesNo
将是1
而对于其余未选择行数将为 0。 - 所以在这个例子中,这将以一个具有
1000
值的新列结束,其中 3*20 个将具有 1(3-> 分配给 class 的行数最低计数,20-> 是 classes 的数量),其余为 0。
我想知道如何在 MATLAB R2015b 中完成此操作?我知道我可以使用 T.YesNo = newArr;
在 table 中创建一个新列,其中 newArr
是具有 0
和 1
值的 1000x1 double
。
作为一个小例子,如果 T
是 10x3
并且只有 3 个 classes (1,2,3
),下面是 T
的样子:
ID Name Class
0 'a' 3
1 'b' 2
2 'a' 2
3 'b' 2
4 'a' 3
5 'a' 1
6 'a' 1
7 'b' 2
8 'b' 1
9 'a' 2
因此,如上所示,Class3 是计数最少的,只有 2 行。所以我想随机 select 两行 Class1 和 Class2 然后将这些随机 selected 行的新列的值设置为 1
而其余的将是 0
,如下所示:
ID Name Class YesNo
0 'a' 3 1
1 'b' 2 0
2 'a' 2 1
3 'b' 2 0
4 'a' 3 1
5 'a' 1 0
6 'a' 1 1
7 'b' 2 0
8 'b' 1 1
9 'a' 2 1
见下面的代码。它应该是不言自明的。如果有什么不清楚 - 请询问。
function q42944288
%% Definitions
MAX_CLASS = 20;
%% Setup
tmp = struct;
tmp.Data = rand(1000,1);
tmp.Class = uint8(randi(MAX_CLASS,1000,1)); % uint8 for efficiency
T = table(tmp.Data,tmp.Class,'VariableNames',{'Data','Class'});
%% Solution:
% Step 1:
[count,minVal] = min(histcounts(T.Class,'BinMethod','integers'));
% Steps 2+3:
T.YesNo = T.Class == minVal;
% Steps 4+5+6:
whichClass = bsxfun(@eq,T.Class,1:MAX_CLASS); % >=R2007a syntax
% whichClass = T.Class == 1:MAX_CLASS; % This is a logical array, >=R2016b syntax.
for indC = setdiff(1:MAX_CLASS,minVal)
inds = find(whichClass(:,indC));
T.YesNo(inds(randperm(numel(inds),count))) = true;
end
%% Test:
fprintf(1,'\nThe total number of classes is %d', numel(unique(T.Class)));
fprintf(1,'\nThe minimal count is %d',count);
fprintf(1,'\nThe total number of 1''s in T.YesNo is %d', sum(T.YesNo));