1

如果AB是具有相同列(并且顺序相同)的表(或数据集),则表达式 likeismember(A(:, somecols), B(:, somecols))将生成一个适合索引的布尔数组A,如

A(ismember(A(:, somecols), B(:, somecols)), :)

上面的行计算为 a table(或dataset,取决于 的类),其中包含与中指定的列中的某行匹配A的那些行。ABsomecols

但现在假设它B正好有一排。更现实地,假设从中选择行的标准A只是匹配的单行B比如第一行。

可以这样做:

A(ismember(A(:, somecols), B(1, somecols)), :)

我对此的主要疑问是它不是“语义清晰”,因为ismember它实际上被用来测试是否相等。

如果可以写的话,语义上会更清晰

A(isequal(A(:, somecols), B(1, somecols)), :)

但这确实不会产生预期的结果。(具体来说,即使A(:, ...)包含匹配的行,它也不返回匹配项B(1, ...)。)

我的问题是,将正确产生与问题“此行是否与此参考行A匹配”对应的逻辑向量的谓词是什么?somecols

4

2 回答 2

3

对于table数据类型,您也可以使用innerjoin,但ismember在这种情况下相当清楚。考虑tablesAtBt,其中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的行的索引。与您的示例一样,请考虑由以下指定的列的子集:ABsomecols

>> 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
于 2014-02-04T01:58:13.197 回答
1

我同意使用该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)),:);
于 2014-02-04T01:03:59.753 回答