SAS SQL 循环输入顺序文件
SAS SQL Loop Inputting Sequential Files
我有:
6个文件,命名如下:"ROSTER2008", "ROSTER2009", ..., "ROSTER2013"
每个文件都有这些变量:TEAMID 和 MATE1、MATE2、...、MATEX。为每个团队存储队友的名字,直到队友 X。
现在:我想遍历读取 6 个文件的代码并创建一个包含 TEAM、MATES2008、MATES2009、...、MATES2013 的输出文件,其中 MATES20XX 变量包含每个团队的队友数量那一年(我不再关心他们的名字)。
这是我尝试做的事情:
%macro sqlloop(start, end);
proc sql;
%DO year=&start. %TO &end.;
create table mates_by_team_&year. as
select distinct put(teamID, z2.) as team,
count(*) as mates
from myLibrary.rosters
where d='ROSTER(HOW DO I PUT YEAR HERE?)'.d;
%end;
quit;
%mend;
%sqlloop(start=2008, end=2013)
所以,这是我的问题:
如何修复 'where' 语句,使其能够理解我打算在每次迭代中引入的文件名? (即ROSTER2008,...,ROSTER2013)
现在,我正在为我输入的每个文件创建 6 个不同的 table。相反,我如何才能将这些文件合并为一个 table,正如我上面所描述的?
提前感谢您的帮助!
Xtina
假设这些是 SAS 数据集并且您使用的是 SAS 9.3+,我建议您使用数据步长和 proc freq 方法。它更容易理解。如果你想让它成为一个宏,用你的宏变量替换年份 (2008/2012)。
编辑:添加 N() 来计算队友的数量,假设它遵循 mate1 mate2 ... matex。
单个数据步会有答案,您可以删除变量。
Data combined;
Set roster2008 - roster2012 indsname=source;
Year = substr(scan(source, 2, '.'), 7);
Num_mates = n(of mate:);
*drop mate:;
Run;
PROC sort data=combined;
By teamid year;
Run;
PROC transpose data=combined out=want prefix=mate;
By teamid;
VAR num_mates;
Id year;
Run;
*OLD CODE BASED ON SQL SOLUTION;
*Proc freq data=combined;
*Table dsn*teamid/list;
*Run;
为了简单起见,我假设你在 MATEX 中的 X 永远不会超过 999。显然你可以增加限制或您可以使用 proc contents 或字典表找出最大限制。
我把所有变量 Mate1:MateX 拉到一个数组中,检查它们是否丢失,并增加计数器来计算队友的数量。
%macro loops(start=,end=);
%do year=&start. %to &end.;
data year_&year.(keep=teamid Mates_&year.);
set roster&year.;
array mates{*} mate1-mate999;
Mates_&year.=0;
do i=1 to 999;
if not missing(mates{i}) then Mates_&year.=Mates_&year.+1;
end;
run;
proc sort data=year_&year.;
by teamid;
%end;
最后我将所有数据集合并在一起。
data team;
merge year_&start.-year_&end.;
by teamid;
run;
%mend;
%loops(start=2008,end=2009);
我有: 6个文件,命名如下:"ROSTER2008", "ROSTER2009", ..., "ROSTER2013" 每个文件都有这些变量:TEAMID 和 MATE1、MATE2、...、MATEX。为每个团队存储队友的名字,直到队友 X。
现在:我想遍历读取 6 个文件的代码并创建一个包含 TEAM、MATES2008、MATES2009、...、MATES2013 的输出文件,其中 MATES20XX 变量包含每个团队的队友数量那一年(我不再关心他们的名字)。
这是我尝试做的事情:
%macro sqlloop(start, end);
proc sql;
%DO year=&start. %TO &end.;
create table mates_by_team_&year. as
select distinct put(teamID, z2.) as team,
count(*) as mates
from myLibrary.rosters
where d='ROSTER(HOW DO I PUT YEAR HERE?)'.d;
%end;
quit;
%mend;
%sqlloop(start=2008, end=2013)
所以,这是我的问题:
如何修复 'where' 语句,使其能够理解我打算在每次迭代中引入的文件名? (即ROSTER2008,...,ROSTER2013)
现在,我正在为我输入的每个文件创建 6 个不同的 table。相反,我如何才能将这些文件合并为一个 table,正如我上面所描述的?
提前感谢您的帮助!
Xtina
假设这些是 SAS 数据集并且您使用的是 SAS 9.3+,我建议您使用数据步长和 proc freq 方法。它更容易理解。如果你想让它成为一个宏,用你的宏变量替换年份 (2008/2012)。
编辑:添加 N() 来计算队友的数量,假设它遵循 mate1 mate2 ... matex。 单个数据步会有答案,您可以删除变量。
Data combined;
Set roster2008 - roster2012 indsname=source;
Year = substr(scan(source, 2, '.'), 7);
Num_mates = n(of mate:);
*drop mate:;
Run;
PROC sort data=combined;
By teamid year;
Run;
PROC transpose data=combined out=want prefix=mate;
By teamid;
VAR num_mates;
Id year;
Run;
*OLD CODE BASED ON SQL SOLUTION;
*Proc freq data=combined;
*Table dsn*teamid/list;
*Run;
为了简单起见,我假设你在 MATEX 中的 X 永远不会超过 999。显然你可以增加限制或您可以使用 proc contents 或字典表找出最大限制。
我把所有变量 Mate1:MateX 拉到一个数组中,检查它们是否丢失,并增加计数器来计算队友的数量。
%macro loops(start=,end=);
%do year=&start. %to &end.;
data year_&year.(keep=teamid Mates_&year.);
set roster&year.;
array mates{*} mate1-mate999;
Mates_&year.=0;
do i=1 to 999;
if not missing(mates{i}) then Mates_&year.=Mates_&year.+1;
end;
run;
proc sort data=year_&year.;
by teamid;
%end;
最后我将所有数据集合并在一起。
data team;
merge year_&start.-year_&end.;
by teamid;
run;
%mend;
%loops(start=2008,end=2009);