Loops 变量的sas循环超过一个月
我正在尝试循环一系列的日期,以便在它们之间创建日期。这将以月为单位进行,始终显示相应月份的最后一天。给出了开始和结束日期(第一个日期和最后一个日期),而最后一个日期应始终指上个月的结束Loops 变量的sas循环超过一个月,loops,date,sas,Loops,Date,Sas,我正在尝试循环一系列的日期,以便在它们之间创建日期。这将以月为单位进行,始终显示相应月份的最后一天。给出了开始和结束日期(第一个日期和最后一个日期),而最后一个日期应始终指上个月的结束 data want ; set have ; do offset=0 to intck('month',first_date,last_date)-1; date=intnx('month',first_date,offset,'e'); output; end; format d
data want ;
set have ;
do offset=0 to intck('month',first_date,last_date)-1;
date=intnx('month',first_date,offset,'e');
output;
end;
format date yymmdd10.;
run;
原始数据集如下所示:
customer id first_date last_date
xy 135 01.01.2000 25.03.2005
xy 247 19.03.2003 25.03.2005
ab 387 01.06.2010 30.12.2012
ab 128 01.05.2010 28.02.2011
...
我的目标是创建一个如下所示的数据集:
customer id date
xy 135 31.01.2000
xy 135 28.02.2000
...
xy 135 28.02.2005
xy 247 31.03.2003
xy 247 30.04.2003
...
xy 247 28.02.2005
我发现迭代天数的解决方案非常简单(见下文),但我很难实现每月步骤和月末日期
data want;
set have;
by customer id;
do day = first_date to last_date;
output;
end;
format day date9.;
run;
谢谢你的帮助 首先,让我们获取一些数据:
data have;
attrib customer length=$10 informat=$10.
id informat=best.
first_date informat=ddmmyy10. format=ddmmyy10.
last_date informat=ddmmyy10. format=ddmmyy10.
;
input customer $
id
first_date
last_date
;
datalines;
xy 135 01.01.2000 25.03.2005
xy 247 19.03.2003 25.03.2005
ab 387 01.06.2010 30.12.2012
ab 128 01.05.2010 28.02.2011
;
run;
intnx()
函数将在这里起到解救作用。我们将创建一个名为date的新变量,然后使用intnx函数返回该日期的月末。只要该日期小于结束日期,我们将继续将其输出到数据集,然后递增到下个月底
data want;
format date ddmmyy10.;
set have;
date = intnx('month',first_date,0,'end');
do while (date le last_date);
output;
date = intnx('month',date,1,'end');
end;
drop first_date last_date;
run;
虽然我认为Rob的答案是正确的,但看看如何用你尝试的方式来做可能会有所帮助 从这一点开始:
data want;
set have;
by customer id;
do day = first_date to last_date;
output;
end;
format day date9.;
run;
这会给你太多的行,对吗?所以你需要做的是确定你在这个月的位置。有很多方法可以做到这一点。几个日期函数(如INTNX和INTCK)可以用来告诉你在哪里;但最简单的方法是将月(日期)
与月(日期+1)
进行比较。当他们不一样的时候,你是在一个月的最后一天
data want;
set have;
by customer id notsorted;
do day = first_date to last_date;
if month(day) ne month(day+1) then output;
end;
format day date9.;
run;
(我添加了notsorted
,因为Rob的示例数据没有排序,我很懒。在您的实际案例中可能不需要。)
我要指出的是,这可能不是您理想的解决方案——Rob的可能是,就数据步数而言——就速度而言。当然,这将每天迭代,而不是每月迭代一次。如果您有上面创建的数据集(每天一行),另一个选项是使用,如果您有ETS模块。这样的东西很方便
data intermediate;
set have;
by customer id notsorted;
do day = first_date to last_date;
output;
end;
format day date9.;
run;;;
这是你的日常数据。下面是PROC EXPAND语句,要求每月提供数据,并在末尾对齐<代码>id日期代码>标识时间序列变量,并按客户id排序
是normal by语句(哪些变量标识观察值),带有NOTSORDED
,因此它们之间不必相对有序
proc expand data=intermediate out=want from=day to=month align=end;
id day;
by customer id notsorted;
run;
这给出了一个与Rob和我的另一个解决方案稍有不同的解决方案,因为如果不是在月底,它会给出每个解决方案的最后一行(并将最后一行设置为月底)。如果这是需要的,很好,我们的解决方案可以很容易地进行调整,以实现这一点;如果不需要,您必须在以后删除它。您可以使用日期间隔函数通过简单的迭代
do
循环来完成此操作。从间隔数中减去一,使其在上个月的最后一天结束
data want ;
set have ;
do offset=0 to intck('month',first_date,last_date)-1;
date=intnx('month',first_date,offset,'e');
output;
end;
format date yymmdd10.;
run;
回答得好。我发现将其编写为,
date\u start=intnx('month',first\u date,0,'end')更直观一些(特别是对于习惯于执行x=y到z循环的程序员);do incr=1乘1,而(最后日期);产出;日期=intnx('月份',开始日期,增加日期,'结束');结束代码>你最终得到了同样的结果,这让我更直观。有趣的是,我最近看到了一些答案,人们使用了这种风格,而我以前从未真正看到过。来自compsci的背景,我刚刚在学校学习了3个基本的C型循环(for、while和do…while),我在SAS中使用了相同的循环结构。实际上,这是一个C型循环for(incr=1;date le last_date;incr++)
将是c等价物。SAS只是组织方式有点不同。这非常有效!谢谢!我需要更熟悉intnx函数!好的,详细的问题!如果最后一天实际上是一个月的最后一天呢?(即last_date='2014年12月31日;
)@Joe-如果最后一天是一个月的结束,那么我对请求的理解是他们想要上个月的最后一天。因此,对于2014年12月31日的2014年11月30日的。