SAS 合并来自具有相似名称的数据集的不同记录
SAS union distinct records from datasets with similar names
我有大约 100 个大型数据集,在每个数据集中我希望提取不同的 ID 以垂直连接它们。数据集未排序,命名为 data_01 , data_02, data_03 ....data_100.
由于数据集都非常大,将它们放在一起而不减小大小是不可行的,连接在 运行ning 数小时后甚至没有移动。因此,我认为有必要在堆叠之前减少数据集,我在这里寻求一些帮助。
我试图为 select 不同的 ID 创建一个宏,并在通过 proc sql union 垂直连接所有数据集之前按 ID 对数值变量 cnt 求和。宏无法正常工作:
/*Get dataset names*/
proc sql noprint;
select memname into :mylist separated by ' '
from dictionary.tables where libname= "mylib" and upcase(memname) like "DATA_%"
;
quit;
%put &mylist;
/*create union statements*/
%global nextdata;
%let nextdata =;
%macro combinedata(mylist);
data _null_;
datanum = countw("&mylist");
call symput('Dataset', put(datanum, 10.));
run;
%do i = 1 %to &Dataset ;
data _null_;
temp = scan("&mylist", &i);
call symput("Dataname", strip(put(temp,.)));
run;
%put &Dataname;
%put &Dataset;
%if (&i=&Dataset) %then %do;
%let nextdata = &nextdata.
select id, sum(cnt)
from mylib.&&Dataname
group by id;
%end;
%else %do;
%let nextdata = &nextdata.
select id, sum(cnt)
from mylib.&&Dataname union
group by id;
%end;
%put nextdata = &nextdata;
%end;
%mend combinedata;
%combinedata(&mylist);
/*execute from proc sql*/
proc sql;
create table combined as (&nextdata);
quit;
我也尝试过使用 proc summary,但是没有足够的内存来 运行 以下代码:
data vneed / view=vneed;
set data_: (keep=id cnt);
run;
proc summary data=vneed nway;
class id;
var cnt;
output out=want (drop=_type_) sum=sumcnt;
run;
感谢任何帮助!
如果 ID 值的数量合理,您应该可以使用哈希对象。
data _null_ ;
if _n_=1 then do;
dcl hash H (ordered: "A") ;
h.definekey ("ID") ;
h.definedata ("ID", "SUMCNT") ;
h.definedone () ;
end;
set data_: (keep=id cnt) end=eof;
if h.find() then sumcnt=.;
sumcnt+cnt ;
h.replace() ;
if eof then h.output (dataset: "WANT") ;
run ;
如果 ID 值的数量太大而无法将摘要数据放入 HASH 对象,您可以调整此代码以停止在某个合理数量的不同 ID 值处以避免内存过载并将当前摘要写入实际SAS 数据集,然后通过重新聚合中间数据集生成最终计数。但那时你应该只使用我的其他答案,让 PROC SQL 创建中间摘要数据集。
边走边总结数据,而不是尝试生成一个庞大的查询。然后重新聚合聚合。
proc sql ;
%do i = 1 %to &Dataset ;
%let dataname=mylib.%scan(&mylist,&i,%str( ));
create table sum&i as
select id,sum(cnt) as cnt
from &dataname
group by id
order by id
;
%end;
quit;
data want ;
do until(last.id);
set sum1 - sum&dataset ;
by id;
sumcnt+cnt;
end;
drop cnt;
run;
我有大约 100 个大型数据集,在每个数据集中我希望提取不同的 ID 以垂直连接它们。数据集未排序,命名为 data_01 , data_02, data_03 ....data_100.
由于数据集都非常大,将它们放在一起而不减小大小是不可行的,连接在 运行ning 数小时后甚至没有移动。因此,我认为有必要在堆叠之前减少数据集,我在这里寻求一些帮助。
我试图为 select 不同的 ID 创建一个宏,并在通过 proc sql union 垂直连接所有数据集之前按 ID 对数值变量 cnt 求和。宏无法正常工作:
/*Get dataset names*/
proc sql noprint;
select memname into :mylist separated by ' '
from dictionary.tables where libname= "mylib" and upcase(memname) like "DATA_%"
;
quit;
%put &mylist;
/*create union statements*/
%global nextdata;
%let nextdata =;
%macro combinedata(mylist);
data _null_;
datanum = countw("&mylist");
call symput('Dataset', put(datanum, 10.));
run;
%do i = 1 %to &Dataset ;
data _null_;
temp = scan("&mylist", &i);
call symput("Dataname", strip(put(temp,.)));
run;
%put &Dataname;
%put &Dataset;
%if (&i=&Dataset) %then %do;
%let nextdata = &nextdata.
select id, sum(cnt)
from mylib.&&Dataname
group by id;
%end;
%else %do;
%let nextdata = &nextdata.
select id, sum(cnt)
from mylib.&&Dataname union
group by id;
%end;
%put nextdata = &nextdata;
%end;
%mend combinedata;
%combinedata(&mylist);
/*execute from proc sql*/
proc sql;
create table combined as (&nextdata);
quit;
我也尝试过使用 proc summary,但是没有足够的内存来 运行 以下代码:
data vneed / view=vneed;
set data_: (keep=id cnt);
run;
proc summary data=vneed nway;
class id;
var cnt;
output out=want (drop=_type_) sum=sumcnt;
run;
感谢任何帮助!
如果 ID 值的数量合理,您应该可以使用哈希对象。
data _null_ ;
if _n_=1 then do;
dcl hash H (ordered: "A") ;
h.definekey ("ID") ;
h.definedata ("ID", "SUMCNT") ;
h.definedone () ;
end;
set data_: (keep=id cnt) end=eof;
if h.find() then sumcnt=.;
sumcnt+cnt ;
h.replace() ;
if eof then h.output (dataset: "WANT") ;
run ;
如果 ID 值的数量太大而无法将摘要数据放入 HASH 对象,您可以调整此代码以停止在某个合理数量的不同 ID 值处以避免内存过载并将当前摘要写入实际SAS 数据集,然后通过重新聚合中间数据集生成最终计数。但那时你应该只使用我的其他答案,让 PROC SQL 创建中间摘要数据集。
边走边总结数据,而不是尝试生成一个庞大的查询。然后重新聚合聚合。
proc sql ;
%do i = 1 %to &Dataset ;
%let dataname=mylib.%scan(&mylist,&i,%str( ));
create table sum&i as
select id,sum(cnt) as cnt
from &dataname
group by id
order by id
;
%end;
quit;
data want ;
do until(last.id);
set sum1 - sum&dataset ;
by id;
sumcnt+cnt;
end;
drop cnt;
run;