如何获取与表(或数据集)对象B的某些行匹配的表(或数据集)对象A的所有行?

时间:2014-02-03 21:04:50

标签: matlab

AB为两个table(或dataset个)对象,这些对象具有一些共同的因子变量K1, K2, ..., Kn。我将这些 n 因子称为关键因素。另外,我会说AB 的一行匹配 iff匹配这些关键因素,即iff A.K1 == B.K1 & A.K2 == B.K2 & ... & A.Kn == B.Kn

(我在这篇文章的末尾用代码给出了上面的例子。)

  

我正在寻找一种高效的方式来提取A的所有行,这些行匹配B的一个 1 行。

(更确切地说,我想要生成一个新表C,其中包含“匹配”A行的所有B行。)


有一种有效的方法吗? (我试图在这里避免for - Loop Hell,或者依赖于知道关键因素的数量等等的任何解决方案,因为我想在不太了解的代码中使用它AB直到运行时。)

我尝试了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


以下是我正在考虑的evalA表格的示例。 (对于那些没有支持(而不是新的)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的“索引表”。

1 个答案:

答案 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生成逻辑索引来解决这个问题。