2

在尝试对不同 ID 变量组中的行进行比较时,我需要一些帮助,所有这些都在一个数据集中。

也就是说,如果两个或多个 ID 组中有任何重复的观察,那么我想完全删除观察。

我想识别不同组的行之间的任何重复项并完全删除观察结果。

例如:

ID  Value
 1    A
 1    B
 1    C
 1    D
 1    D
 2    A
 2    C
 3    A
 3    Z
 3    B

我想要的输出是:

ID  Value
 1    D
 3    Z

我在网上查了很多东西,并尝试了一些东西。我想我可以用标志标记重复项,然后根据该标志删除。

标记代码是:

data have;
set want;
flag = first.ID ne last.ID;
run;

这适用于某些情况,但我也标记了同一值组中的重复项。

因此,第一个观察被删除:

ID  Value
 3    Z

我也试过:

data have;
set want;
flag = first.ID ne last.ID and first.value ne last.value;
run;

但这根本没有标记任何重复项。

我将不胜感激任何帮助。如果需要任何其他信息,请告诉我。

谢谢。

4

5 回答 5

4

这是一种相当简单的方法:按值+ ID 排序和去重,然后只保留值仅针对单个ID 出现的行。

data have;
input ID  Value $;
cards;
 1    A
 1    B
 1    C
 1    D
 1    D
 2    A
 2    C
 3    A
 3    Z
 3    B
 ;
run;

proc sort data = have nodupkey;
    by value ID;
run;

data want;
set have;
by value;
if first.value and last.value;
run;

proc sql版本:

proc sql;
create table want as
select distinct ID, value from have
group by value
having count(distinct id) =1
order by id
;
quit;
于 2019-07-23T22:01:12.833 回答
3

这是我对要求的解释。查找仅出现在 1 个 ID 中的值级别。

data have;
   input ID  Value:$1.;
   cards;
 1    A
 1    B
 1    C
 1    D
 1    D
 2    A
 2    C
 3    A
 3    Z
 3    B
;;;;
proc print;
proc summary nway; /*Dedup*/
   class id value;
   output out=dedup(drop=_type_ rename=(_freq_=occr));
   run;
proc print;
   run;
proc summary nway;
   class value;
   output out=want(drop=_type_)  idgroup(out[1](id)=) sum(occr)=;
   run;
proc print;
   where _freq_ eq 1;
   run;
proc print;
   run;

在此处输入图像描述

于 2019-07-23T21:23:38.597 回答
3

稍微不同的方法可以使用散列对象来跟踪属于单个组的唯一值。

data have; input
ID  Value:& $1.; datalines;
 1    A
 1    B
 1    C
 1    D
 1    D
 2    A
 2    C
 3    A
 3    Z
 3    B
run;

proc delete data=want;

proc ds2;
  data _null_;
    declare package hash values();
    declare package hash discards();
    declare double idhave;

    method init();
      values.keys([value]);
      values.data([value ID]);
      values.defineDone();

      discards.keys([value]);
      discards.defineDone();
    end;

    method run();
      set have;

      if discards.find() ne 0 then do;
        idhave = id;
        if values.find() eq 0 and id ne idhave then do;
          values.remove();
          discards.add();
        end;
        else
          values.add();
      end;
    end;

    method term();
      values.output('want');
    end;
  enddata;
  run;
quit;

%let syslast = want;
于 2019-07-24T08:28:22.963 回答
2

我认为你应该做的是:

data want;
  set have;
  by ID value;   
  if not first.value then flag = 1;
  else flag = 0;
run;

这基本上标记了一个值的所有出现,除了给定 ID 的第一个值。

我也改变了想要并假设你want从你创造了什么have。我还假设have按 ID 值顺序排序。

这也只会1 D在上面标记。不是3 Z

附加输入

你不能做一个排序来摆脱重复:

proc sort data = have out = want nodupkey dupout = not_wanted;
  by ID value;
run;
于 2019-07-23T21:12:29.190 回答
0

因此,如果您按 VALUE 级别(而不是按 ID 级别)处理观察结果,那么您只需要跟踪是否有任何 ID 与第一个不同。

data want ;
  do until (last.value);
    set have ;
    by value ;
    if first.value then first_id=id;
    else if id ne first_id then remapped=1;
  end;
  if not remapped;
  keep value id;
run;
于 2019-07-24T22:23:50.910 回答