我需要加载到Teradata中的大型SAS数据集(54个变量和超过1000万个观测值)。还有重复项,并且我的机器没有配置为MultiLoad。我想简单地创建一个包含300,000个重复项的表,我可以附加到不接受它们的原始加载。我在其他帖子中读到的逻辑对于只有几个变量的表来说似乎很好。是否有另一种方法可以创建一个新表,其中列出了具有所有54个变量的相同组合的每个观察。我试图通过使用54个变量的逻辑来避免proc排序。查询构建器方法似乎效率低下。感谢。
答案 0 :(得分:1)
使用proc sort
是一种很好的方法,你只需要创建一种更好的方法来关闭它。
创建一些测试数据。
data have;
x = 1;
y = 'a';
output;
output;
x = 2;
output;
run;
创建一个新字段,该字段基本上等同于将行中的所有字段附加在一起,然后通过md5()
(散列)算法运行它们。这将为您提供一个很好的短字段,它将唯一地标识该行上所有值的组合。
data temp;
length hash $16;
set have;
hash = md5(cats(of _all_));
run;
现在使用proc sort和我们的新哈希字段作为键。将重复记录输出到名为'想要':
的表中proc sort data=temp nodupkey dupout=want;
by hash;
run;
答案 1 :(得分:0)
您可以这样做:
proc sql;
create table rem_dups as
select <key_fields>, count(*) from duplicates
group by <key_fields>
having count(*) > 1;
quit;
proc sql;
create table target as
select dp.* from duplicates dp
left join rem_dups rd
on <Key_fields>
where <key_fields> is null;
quit;
如果重复次数超过300K,则此选项不起作用。而且,我不敢说我不知道Teradata和你加载表格的方式。
答案 2 :(得分:0)
首先,提出一些sort
相关建议,然后是休息后的核心“快速”建议。
如果表格完全未排序(即重复项可以出现在数据集中的任何位置),那么proc sort
可能是您最简单的选项。如果您有一个密钥可以保证将重复记录放在一起,那么您可以这样做:
proc sort data=have out=uniques noduprec dupout=dups;
by <key>;
run;
这将在辅助数据集(上面的noduprec
)中放置重复记录(注意nodupkey
而非dups
- 这要求所有54个变量相同)。但是,如果它们在物理上并不相邻(即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不要抱怨,但是让你先使用/最后一次。不是一个很好的选择,特别是因为你需要指定一切。
执行此操作的最快方法可能是使用哈希表, iff 您有足够的RAM来处理它,或者您可以以某种方式破坏表(不会丢失重复项) )。 10m行乘以54(比如说10个字节)变量意味着5.4GB的数据,所以这只有在你有5.4GB的RAM可用于制作散列表的情况下才有效。
如果您知道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;
答案 3 :(得分:-2)
我建议您将Proc sort
与index
一起使用,而不是试图避免proc排序。
我确信必须有标识符来区分_n_
以外的观察,
在索引的帮助下,按noduprecs
或nodupkey
dupout = dataset
排序将是一种有效的选择。此外,索引还可以促进其他操作,例如合并/报告。
无论如何,我不认为拥有1000万个观测数据(每个?)的数据集是一个很好的数据集,更不用说54个变量了。