如果A
和B
是具有相同列(并且顺序相同)的表(或数据集),那么像ismember(A(:, somecols), B(:, somecols))
这样的表达式将生成一个适合的布尔数组用于索引A
,如
A(ismember(A(:, somecols), B(:, somecols)), :)
上面的一行评估为table
(或dataset
,具体取决于A
的类),其中A
行与B
的某一行匹配1}}在somecols
。
但现在假设B
只有一行。更现实的是,假设从A
中选择行的标准只是匹配 B
的这一行,比如第一行。
可以这样做:
A(ismember(A(:, somecols), B(1, somecols)), :)
我对此的主要狡辩是它不是“语义清晰”,因为实际上使用ismember
来测试相等性。
如果可以写
,那将在语义上更清晰A(isequal(A(:, somecols), B(1, somecols)), :)
但这确实不会产生预期的效果。 (具体而言,即使A(:, ...)
包含与B(1, ...)
匹配的行,也不返回任何匹配项。)
我的问题是,什么是正确生成与问题相对应的逻辑向量的谓词“A
这一行匹配 参考行somecols
” ?
答案 0 :(得分:3)
对于table
data type,您也可以使用innerjoin
,但ismember
在这种情况下非常明确。考虑table
s 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
答案 1 :(得分: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)),:);