让A
和B
为两个table
(或dataset
个)对象,这些对象具有一些共同的因子变量K1, K2, ..., Kn
。我将这些 n 因子称为关键因素。另外,我会说A
和B
的一行匹配 iff匹配这些关键因素,即iff A.K1 == B.K1 & A.K2 == B.K2 & ... & A.Kn == B.Kn
。
(我在这篇文章的末尾用代码给出了上面的例子。)
我正在寻找一种高效的方式来提取
A
的所有行,这些行匹配B
的一个 1 行。
(更确切地说,我想要生成一个新表C
,其中包含“匹配”A
行的所有B
行。)
有一种有效的方法吗? (我试图在这里避免for
- Loop Hell,或者依赖于知道关键因素的数量等等的任何解决方案,因为我想在不太了解的代码中使用它A
和B
直到运行时。)
我尝试了intersect(A, B)
,但失败并出现错误:
>> keyfactors = intersect(A.Properties.VarNames, B.Properties.VarNames);
>> intersect(A, B, keyfactors)
Error using table/intersect (line 41)
A and B must contain the same variables.
我能想出的唯一其他策略(虽然我还不知道如何实现它)是基于{中编码的信息在某种程度上合成一个函数。 {1}}。例如,给定一个像这样的索引表B
B
...以某种方式以编程方式生成类似
的函数B = cell2table({
'even', 'red', 'diamonds';
'odd', 'yellow', 'spades';
'odd', 'green', 'hearts'
}, 'VariableNames', ...
{'Parity', 'TrafficLight', 'Suit'});
...然后可以在这样的表达式中使用:
fn = @(c) any([all([strcmp(c(:, 1), 'even'), ...
strcmp(c(:, 2), 'red'), ...
strcmp(c(:, 3), 'diamonds')], 2), ...
all([strcmp(c(:, 1), 'odd'), ...
strcmp(c(:, 2), 'yellow'), ...
strcmp(c(:, 3), 'spades')], 2), ...
all([strcmp(c(:, 1), 'odd'), ...
strcmp(c(:, 2), 'green'), ...
strcmp(c(:, 3), 'hearts')], 2)], 2);
不幸的是,我无法弄清楚如何以编程方式合成上面的Ac = table2cell(A);
C = cell2table(Ac(fn(Ac), :), ...
'VariableNames', B.Properties.VariableNames);
这样的函数,而不依赖于(强烈弃用)fn
。
以下是我正在考虑的eval
和A
表格的示例。 (对于那些没有支持(而不是新的)B
对象的MATLAB版本的人,如果字符串“table”和“VariableNames”被字符串“dataset”替换,则下面的代码应该有效。 “VarNames”,分别为。)
table
1 可以安全地假设,在% "data" table
A = cell2table({
'even', 'red', 'spades', 38, 0.9837;
'even', 'red', 'hearts', 19, 0.5695;
'even', 'red', 'diamonds', 89, 0.2629;
'even', 'red', 'diamonds', 98, 0.3578;
'even', 'red', 'diamonds', 92, 0.2596;
'even', 'red', 'diamonds', 69, 0.5751;
'even', 'red', 'diamonds', 77, 0.6318;
'even', 'yellow', 'clubs', 22, 0.6917;
'even', 'green', 'spades', 35, 0.6674;
'even', 'green', 'hearts', 67, 0.7896;
'even', 'green', 'hearts', 49, 0.5025;
'even', 'green', 'hearts', 64, 0.5318;
'odd', 'red', 'spades', 22, 0.5587;
'odd', 'red', 'hearts', 51, 0.9122;
'odd', 'red', 'diamonds', 74, 0.3343;
'odd', 'red', 'diamonds', 69, 0.2911;
'odd', 'yellow', 'spades', 33, 0.2653;
'odd', 'yellow', 'spades', 38, 0.2549;
'odd', 'yellow', 'diamonds', 1, 0.2064;
'odd', 'yellow', 'diamonds', 25, 0.8257;
'odd', 'green', 'spades', 64, 0.4348;
'odd', 'green', 'hearts', 59, 0.8644;
'odd', 'green', 'hearts', 4, 0.6374;
'odd', 'green', 'hearts', 11, 0.3354
}, 'VariableNames', ...
{'Parity', 'TrafficLight', 'Suit', 'order', 'prevalence'});
% "indexing" table
B = cell2table({
'i', 'even', 'red', 'diamonds';
'ii', 'odd', 'yellow', 'spades';
'iii', 'odd', 'green', 'hearts'
}, 'VariableNames', ...
[{'class'} A.Properties.VariableNames(1:3)]);
keyfactors = intersect(B.Properties.VariableNames, ...
A.Properties.VariableNames, ...
'stable');
% this fails:
% intersect(A, B, keyfactors);
% desired subtable would look like this one
C = cell2table({
'even', 'red', 'diamonds', 89, 0.2629;
'even', 'red', 'diamonds', 98, 0.3578;
'even', 'red', 'diamonds', 92, 0.2596;
'even', 'red', 'diamonds', 69, 0.5751;
'even', 'red', 'diamonds', 77, 0.6318;
'odd', 'yellow', 'spades', 33, 0.2653;
'odd', 'yellow', 'spades', 38, 0.2549;
'odd', 'green', 'hearts', 59, 0.8644;
'odd', 'green', 'hearts', 4, 0.6374;
'odd', 'green', 'hearts', 11, 0.3354
}, 'VariableNames', ...
{'Parity', 'TrafficLight', 'Suit', 'order', 'prevalence'});
中,关键因素的任何值组合(也称为“级别”)最多只出现一次< / em>的。 B
通常不为真。在实践中,A
将包含实际数据,而A
将是“合成的”(即专门为此处描述的操作构建),并且将具有更少的变量并且更多更少比B
更多的行。因此,可以将A
视为B
的“索引表”。
答案 0 :(得分:3)
这会返回您想要的内容,但我不知道它是否正常工作,因此您需要测试:
[~,iB,iA] = intersect(B.Properties.VariableNames, ...
A.Properties.VariableNames, ...
'stable');
C = A(ismember(A(:,iA),intersect(A(:,iA),B(:,iB),'stable')),:)
部分问题是table/intersect
仅在重复行时返回第一个匹配项。我使用table/ismember
生成逻辑索引来解决这个问题。