algorithm - 在观察可以有不止一个可能的伙伴观察的条件下消除成对的观察

标签 algorithm sas matching

在我当前的项目中,我们有好几次必须根据不同的条件实现匹配。首先是对问题的更详细描述。

我们得到了一个表测试:
键值
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;

该算法似乎有效,至少没有人发现导致错误的输入数据。 但没有人能向我解释它为什么有效,我也不详细了解它是如何工作的。

所以我有几个问题。

  1. 对于所有可能的输入数据组合,该算法是否以正确的方式消除了对?
  2. 如果它确实工作正常,算法的详细工作原理是什么?尤其是
    其中 tmp_id1 = tmp_id2。
  3. 是否有更好的算法来消除对应对?

提前致谢,编码愉快
迈克尔

最佳答案

作为对第三个问题的回答。以下方法对我来说似乎更简单。 并且可能性能更高。 (因为我没有加入)

/*For every (absolute) value, find how many more positive/negative occurrences we have per key*/
proc sql;
    create view V_INTERMEDIATE_VIEW as
    select key, abs(Value) as Value_abs, sum(sign(value)) as balance
    from INPUT_DATA
    group by key, Value_abs
    ;
quit;

*The balance variable here means how many times more often did we see the positive than the negative of this value. I.e., how many of either the positive or the negative were we not able to eliminate;

/*Now output*/
data OUTPUT_DATA (keep=key Value);
    set V_INTERMEDIATE_VIEW;
    Value = sign(balance)*Value_abs; *Put the correct value back;

    do i=1 to abs(balance) by 1;
        output;
    end;
run;




如果你只想要纯 SAS(所以没有 proc sql),你可以按照下面的方式进行。请注意,它背后的想法保持不变。

data V_INTERMEDIATE_VIEW /view=V_INTERMEDIATE_VIEW;
    set INPUT_DATA;
    value_abs = abs(value);
run;
proc sort data=V_INTERMEDIATE_VIEW out=INTERMEDIATE_DATA;
    by key value_abs; *we will encounter the negatives of each value and then the positives;
run;

data OUTPUT_DATA (keep=key value);
    set INTERMEDIATE_DATA;
    by key value_abs;

    retain balance 0;
    balance = sum(balance,sign(value));

    if last.value_abs then do;
        value = sign(balance)*value_abs; *set sign depending on what we have in excess;            
        do i=1 to abs(balance) by 1;
            output;
        end;

        balance=0; *reset balance for next value_abs;
    end;
run;

注意:感谢 Joe 提供的一些有用的性能建议。

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

相关文章:

java - Graphics.Path.Direction - Java 枚举方向问题 - 无法使用 EAST

input - SAS如何读取输入中的@@?

sas - 在 SAS 中读取超过 32767 个字符的文本行

sas - 如何 "unpivot"数据集 : create multiple rows from a count variable

exception - 打开输入 channel 的 Ocaml 异常处理

algorithm - 2/3D 几何 : How to optimally align two lists of points

algorithm - 比较两个大型电子邮件地址列表的最佳方法或算法是什么?

regex - 检查两个模式是否相互匹配?

algorithm - A*什么时候终止

python - Opencv Python - 来自特征匹配+单应性的相似度分数