先是几个sort相关的建议,然后是休息后的核心“快”建议。
如果表完全未排序(即重复项可以出现在数据集中的任何位置),那么proc sort 可能是您最简单的选择。如果您有一个可以保证将重复记录相邻放置的键,那么您可以这样做:
proc sort data=have out=uniques noduprec dupout=dups;
by <key>;
run;
这会将重复记录(注意 noduprec 不是 nodupkey - 这要求所有 54 个变量都相同)放在辅助数据集中(上面的 dups)。但是,如果它们在物理上不相邻(即,key 有 4 或 5 个重复项,但只有两个是完全重复的),如果它们在物理上不相邻,则可能无法识别;您需要进行第二次排序,或者您需要在 by 语句中列出所有变量(这可能很混乱)。您还可以使用 Rob 的 md5 技术来简化这一点。
如果表未“排序”但重复记录将相邻,您可以使用 by 和 notsorted 选项。
data uniques dups;
set have;
by <all 54 variables> notsorted;
if not (first.<last variable in the list>) then output dups;
else output uniques;
run;
这告诉 SAS 如果事情的顺序不正确,不要抱怨,而是让您使用第一个/最后一个。虽然不是一个很好的选择,但特别是因为您需要指定所有内容。
最快的方法可能是为此使用哈希表,如果你有足够的 RAM 来处理它,或者你可以以某种方式分解你的表(不会丢失你的重复)。 10m 行乘以 54(比如 10 字节)变量意味着 5.4GB 的数据,所以这只有在您有 5.4GB 的 RAM 可供 SAS 用于制作哈希表时才有效。
如果您知道 54 个变量中的一个子集足以验证唯一性,那么 unique 哈希只需包含这些变量子集(即,它可能只有四个或五个索引变量)。 dups 哈希表必须包含所有变量(因为它将用于输出重复项)。
这通过使用modify 来快速处理数据集,而不是重写大部分观察结果;使用remove 删除它们并使用哈希表output 方法将重复项输出到新数据集。 unq 哈希表仅用于查找 - 因此,同样,它可以包含变量的子集。
我在这里还使用了一种技术,将完整的变量列表放入一个宏变量中,这样您就不必输入 54 个变量了。
data class; *make some dummy data with a few true duplicates;
set sashelp.class;
if age=15 then output;
output;
run;
proc sql;
select quote(name)
into :namelist separated by ','
from dictionary.columns
where libname='WORK' and memname='CLASS'
; *note UPCASE names almost always here;
quit;
data class;
if 0 then set class;
if _n_=1 then do; *make a pair of hash tables;
declare hash unq();
unq.defineKey(&namelist.);
unq.defineData(&namelist.);
unq.defineDone();
declare hash dup(multidata:'y'); *the latter allows this to have dups in it (if your dups can have dups);
dup.defineKey(&namelist.);
dup.defineData(&namelist.);
dup.defineDone();
end;
modify class end=eof;
rc_c = unq.check(); *check to see if it is in the unique hash;
if rc_c ne 0 then unq.add(); *if it is not, add it;
else do; *otherwise add it to the duplicate hash and mark to remove it;
dup.add();
delete_check=1;
end;
if eof then do; *if you are at the end, output the dups;
rc_d = dup.output(dataset:'work.dups');
end;
if delete_check eq 1 then remove; *actually remove it from unique dataset;
run;