如果A
和B
是具有相同列(并且顺序相同)的表(或数据集),则像ismember(A(:, somecols), B(:, somecols))
这样的表达式将生成一个适用于索引A
的布尔数组,如
A(ismember(A(:, somecols), B(:, somecols)), :)
上面的行计算为一个table
(或dataset
,取决于A
的类),由那些与somecols
中指定的列中的某行B
A
行匹配的行组成。
但现在假设B
只有一行。 更现实的是,假设从A
中选择行的标准只是匹配这一行B
,比如说第一行。
可以这样做:
A(ismember(A(:, somecols), B(1, somecols)), :)
我对此的主要争论是它不是"语义清楚的",因为ismember
实际上被用来测试平等性。
如果能写,语义会更清晰
A(isequal(A(:, somecols), B(1, somecols)), :)
但这确实不会产生预期的结果。 (具体来说,即使A(:, ...)
包含与B(1, ...)
匹配的行,它也不会返回任何匹配项。
我的问题是,正确生成与问题"这行A
是否与somecols
处的引用行匹配"相对应的逻辑向量的谓词是什么?
对于table
数据类型,您也可以使用innerjoin
,但在这种情况下ismember
相当清楚。考虑table
的At
和Bt
,其中Bt
有两个公共行和一个唯一行:
>> A = randi(7,4,5);
>> commonRows = [1 3];
>> B = [A(commonRows,:); randi(2,1,5)+7];
>> At = array2table(A,'VariableNames',sprintfc('C%d',1:size(A,2)))
At =
C1 C2 C3 C4 C5
__ __ __ __ __
4 1 5 7 7
2 6 5 1 4
4 4 6 7 4
2 7 7 5 6
>> Bt = array2table(B,'VariableNames',sprintfc('C%d',1:size(A,2)))
Bt =
C1 C2 C3 C4 C5
__ __ __ __ __
4 1 5 7 7
4 4 6 7 4
8 8 9 9 9
innerjoin
的第二个输出参数IA
给出了A
中行的索引,这些行也在B
中。与您的示例一样,请考虑由somecols
指定的列子集:
>> somecols = [2 5]
somecols =
2 5
>> [Ct,IA] = innerjoin(At(:,somecols), Bt(1,somecols))
Ct =
C2 C5
__ __
1 7
IA =
1
>> [Ct,IA] = innerjoin(At(:,somecols), Bt(2,somecols))
Ct =
C2 C5
__ __
4 4
IA =
3
>> [Ct,IA] = innerjoin(At(:,somecols), Bt(3,somecols))
Ct =
empty 0-by-2 table
IA =
[]
如果IA
为空(或不为空)是一个合适的测试:
>> [~,IA] = innerjoin(At, Bt(3,:));
>> isempty(IA)
ans =
1
>> [~,IA] = innerjoin(At, Bt(2,:));
>> isempty(IA)
ans =
0
或者只是测试第一个输出,即公共表行:
>> isempty(innerjoin(At, Bt(3,:)))
ans =
1
>> isempty(innerjoin(At, Bt(1,:)))
ans =
0
我同意使用ismember
选项可能不会立即清楚您的意图(尽管它完全没有错)。我想另一种方法可能在语义上更清晰(尽管效率可能较低)是使用这样的bsxfun
:
all(bsxfun(@eq,A(:,somecols),B(1,somecols)),2);
如果你要把它扩展到引擎盖下本质上发生的事情,它会像这样:
a = A(:,somecols);
b = repmat(B(1,somecols),size(A,1),1);
abeq = all(a == b,2);
A(abeq,:);
基本上,您复制B
行,使其大小与A(:,somecols)
相同,然后比较每个数组中的每个值。最后,您检查哪些行具有整行true
(通过使用all
),这表明它与单行 B 匹配。
编辑:抱歉,显然我误解了这个问题 - 如果您使用的是table
数据类型(直到几分钟前我才真正知道存在 - 谢谢 horchler),那么这种方法可能行不通。
EDIT2:Notlikethat指出了函数rowfun
的存在,它作用于表中的每一行。我无法对此进行测试(我的 MATLAB 版本不够新),但我认为这样的东西可以满足您的需求:
A(rowfun(@(x) isequal(B(1,somecols),x),A(:,somecols)),:);