Duplicates 从包含50多个变量的SAS数据集创建重复表

Duplicates 从包含50多个变量的SAS数据集创建重复表,duplicates,sas,Duplicates,Sas,我有一个大型SAS数据集(54个变量和超过1000万个观测值),需要加载到Teradata中。也必须附带一些副本,而且我的机器没有配置为多负载。我只想创建一个包含300000个副本的表,我可以将这些副本附加到不接受它们的原始加载中。我在其他帖子中读到的逻辑似乎适用于只有几个变量的表。是否有另一种方法可以创建一个新表,其中列出了所有54个变量具有相同组合的每个观测值。我试图通过使用54个变量的逻辑来避免proc排序。查询生成器方法似乎效率也很低。谢谢。您可以这样做: proc sql; creat

我有一个大型SAS数据集(54个变量和超过1000万个观测值),需要加载到Teradata中。也必须附带一些副本,而且我的机器没有配置为多负载。我只想创建一个包含300000个副本的表,我可以将这些副本附加到不接受它们的原始加载中。我在其他帖子中读到的逻辑似乎适用于只有几个变量的表。是否有另一种方法可以创建一个新表,其中列出了所有54个变量具有相同组合的每个观测值。我试图通过使用54个变量的逻辑来避免proc排序。查询生成器方法似乎效率也很低。谢谢。

您可以这样做:

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; 
proc-sql;
将表rem_DUP创建为
从重复项中选择、计数(*)
分组
计数(*)大于1;
退出
proc-sql;
将表目标创建为
从重复dp中选择dp.*
左连接rem_dups路
在…上
其中为空;
退出

如果重复项超过300K,则此选项不起作用。另外,我恐怕要说的是,我不知道Teradata和加载表的方式

我建议您将
proc-sort
index
一起使用,而不是试图避免proc-sort

我确信必须有标识符来区分除
\n
以外的观察, 在索引的帮助下,按
noduprecs
nodupkey
dupout=dataset
排序将是一个有效的选择。此外,索引还可以促进其他操作,如合并/报告


无论如何,我不认为一个有1000万个观测值(每个?)的数据集是一个好的数据集,更不用说54个变量了

使用
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和新的散列字段作为键。将重复记录输出到名为“want”的表中:

proc sort data=temp nodupkey dupout=want;
  by hash;
run;

首先,对一些相关建议进行排序,然后是休息后的核心“快速”建议


如果表完全未排序(即,重复项可以出现在数据集中的任何位置),则
proc sort
可能是最简单的选择。如果您有一个密钥可以保证将重复记录放在相邻位置,则可以执行以下操作:

proc sort data=have out=uniques noduprec dupout=dups;
  by <key>;
run;
这告诉SAS如果事情顺序不正确,不要抱怨,但允许您使用first/last。这不是一个很好的选择,尤其是当您需要指定所有内容时


要做到这一点,最快的方法可能是使用哈希表,如果您有足够的RAM来处理它,或者您可以以某种方式分解表(而不会丢失副本)。10m行乘以54(比如说10字节)变量意味着5.4GB的数据,因此只有当SAS有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;

我看不出这是怎么回答这个问题的。我猜他想把所有重复的观测数据放到另一个数据集中。当然,但我不确定
索引
的这一部分与此有什么关系-它现在没有真正的帮助,最后一句也不应该在那里(10毫米观测数据集没有问题,在我的书中这是非常小的)。第三段是合理的。等等,我建议使用带有几个选项的proc排序,这也是很多人建议的。为了提高效率,可以使用索引。为什么要投否决票?否决票主要是针对最后一句话。我仍然不明白索引在这个特定任务中是如何有用的。正如我在最后的评论中所说,第三段是一个合理的答案,尽管他明确要求不要使用proc-sort,所以我认为这是不够的(因此,我在回答中单独回答了如何使用proc-sort),如果数据未排序,您不需要进行两次排序吗?因为noduprecs只删除相邻的重复项,或者SAS已修复该问题?另外,我在sas9.4文档中没有看到noduprecs.Hmm。我以为他们解决了这个问题,但我会看看。(当然,你可以通过按每个字段排序来避免两种排序,但这很混乱。)@Reeza-Hmm,我也看到它在9.4中丢失了。我找不到改变noduprecs的证据,尽管我认为我记得9.4变更日志中的某些内容,所以我现在将调整答案,除非我再次找到它。感谢您捕捉到这一点。我简单地测试了一下,看起来哈希解决方案并没有比Rob的解决方案中的
proc sort
更快(或者只是对整个数据集的变量执行一个nodupkey)。在某些情况下,这可能比proc sort更快,但考虑到所需的代码要多得多,我不认为这是一个更好的解决方案
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;