在我当前的项目中,我们遇到过几次必须根据不同条件实现匹配的情况。首先对问题进行更详细的描述。
我们得到了一个表测试:
key Value
1 10
1 -10
1 10
1 20
1 -10
1 10
2 10
2 -10
现在我们要应用一个规则,以便在一个组(由键的值定义)中消除总和为 0 的对。
预期的结果是:
键值
1 10
1 20
排序顺序不相关。
以下代码是我们解决方案的一个示例。我们希望消除 my_id 为 2 和 7 的观察结果,以及 3 个观察值中的另外 2 个,数量为 10。
data test;
input my_id alias $ amount;
datalines4;
1 aaa 10
2 aaa -10
3 aaa 8000
4 aaa -16000
5 aaa 700
6 aaa 10
7 aaa -10
8 aaa 10
;;;;
run;
/* get all possible matches represented by pairs of my_id */
proc sql noprint;
create table zwischen_erg as
select a.my_id as a_id,
b.my_id as b_id
from test as a inner join
test as b on (a.alias=b.alias)
where a.amount=-b.amount;
quit;
/* select ids of matches to eliminate */
proc sort data=zwischen_erg ;
by a_id b_id;
run;
data zwischen_erg1;
set zwischen_erg;
by a_id;
if first.a_id then tmp_id1 = 0;
tmp_id1 +1;
run;
proc sort data=zwischen_erg;
by b_id a_id;
run;
data zwischen_erg2;
set zwischen_erg;
by b_id;
if first.b_id then tmp_id2 = 0;
tmp_id2 +1;
run;
proc sql;
create table delete_ids as
select zwischen_erg1.a_id as my_id
from zwischen_erg1 as erg1 left join
zwischen_erg2 as erg2 on
(erg1.a_id = erg2.a_id and
erg1.b_id = erg2.b_id)
where tmp_id1 = tmp_id2
;
quit;
/* use delete_ids as filter */
proc sql noprint;
create table erg as
select a.*
from test as a left join
delete_ids as b on (a.my_id = b.my_id)
where b.my_id=.;
quit;
该算法似乎有效,至少没有人发现导致错误的输入数据。但是没有人能向我解释它为什么起作用,我也不详细了解它是如何工作的。
所以我有几个问题。
- 对于输入数据的所有可能组合,该算法是否以正确的方式消除了配对?
- 如果它确实工作正确,那么该算法如何详细工作?尤其是
tmp_id1 = tmp_id2 的部分。 - 有没有更好的算法来消除对应对?
在此先感谢,祝您编码愉快,
迈克尔