在我目前的项目中,我们有几次不得不实现基于不同条件的匹配。首先对问题进行更详细的描述。
我们做了个桌面测试:
关键值
110个
1至10
110个
120个
1至10
110个
210个
2-10个
现在我们要应用一个规则,以便在组(由键的值定义)内消除和为0的对。
预期结果将是:
关键值
110个
120个
排序顺序不相关。
下面的代码是我们解决方案的一个示例。
我们想消除我的id为2和7的观测值,以及数量为10的3个观测值中的额外2个。

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。
有没有更好的算法来消除对应的对?
提前感谢和愉快的编码
迈克尔

最佳答案

快速阅读后我看不到任何错误。但是“zwischen_erg”可能有很多不必要的多对多匹配,这将是低效的。
这似乎有效(但不能保证),而且可能更有效率也更短,所以也许更容易看到发生了什么。

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;

proc sort data=test;
    by alias amount;
run;

data zwischen_erg;
    set test;
    by alias amount;
    if first.amount then occurrence = 0;
    occurrence+1;
run;

proc sql;
    create table zwischen as
    select
        a.my_id,
        a.alias,
        a.amount
    from zwischen_erg as a
    left join zwischen_erg as b
    on a.amount = (-1)*b.amount and a.occurrence = b.occurrence
    where b.my_id is missing;
quit;

关于algorithm - 在以下条件下消除对观测值:观测值可以具有多个可能的伙伴观测值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19406271/

10-13 05:55