我的数据按ID
和日期排序。我已将日期转换为单个数字,该数字具有排序(年份后面是一年中的一周)。我想创建一个新变量,它是最好的分区中最小值的函数。例子如下
ID Start listen
1 201134 201138
1 201204 201150
2 200905 200910
2 201005 201020
我想要像
这样的东西ID开始收听weekSincestart
1 201134 201138 4
1 201204 201150 54
2 200905 200910 5
2 201005 201020 15
我正在做的就是(listen-min(start)
),但我假设min()
正在为给定的ID
采取最小的开始。所以,我问的是min函数是否有“by语句”
答案 0 :(得分:1)
在我看来,没有必要使用你拥有的方法转换你的开始和听日期值。
我使用INTNX将数据转换回日期,使用START和LISTEN变量中的一年中的第一天,并在相同变量中按周递增。日期可能与您在数据集上的日期不完全相同,但它应该会产生类似的结果。
如果我理解正确的话,以下应该做你想做的事。
DATA WANT2;
SET HAVE;
BY ID START;
RETAIN _START;
FORMAT _START DATE9.;
IF FIRST.ID THEN _START = START;
WEEKSINCESTART = INTCK("WEEK",_START,LISTEN);
RUN;
在这种情况下,您的样本已经过排序,但是如果您希望通过语句处理来识别ID中值的第一个实例,则需要先对数据集进行排序。 retain语句将保存一个值,并且通过使用by语句,我们可以指定保留变量中的值何时被更改。在这种情况下,我们希望在遇到ID的第一个实例时更改_START变量。我使用下划线前缀,因为它可以在必要时更容易地放下这些变量。在下一个ID实例之前,不会替换此值,这意味着它将是ID 1的后续观察值,依此类推。 INTCK函数测量间隔的数量,在本例中是周期1和周期2之间的WEEKS数,在这种情况下,在_START中捕获的每个ID的第一个START实例和每个观察的LISTEN之间。
最终结果是:
ID START LISTEN _START WEEKSINCESTART
1 21AUG2011 18SEP2011 21AUG2011 4
1 29JAN2012 11DEC2011 21AUG2011 16
2 01FEB2009 08MAR2009 01FEB2009 5
2 31JAN2010 16MAY2010 01FEB2009 67
我希望这很有用。
此致 斯科特
答案 1 :(得分:0)
您可以使用proc sql轻松完成:
proc sql;
create table RESULT as
select *, listen-min(start) as weekSincestart
from INPUT
group by id;
quit;
每个id组的min将计算min(start)。 并且由于您选择了不在组中的变量,也没有聚合函数,因此它不会将多个行聚合为组中的一个。
答案 2 :(得分:0)
你的问题有点令人困惑。如果你只想听取减去开始(你的“结果”是什么),那就去做吧。 min
函数不会跨行;在SAS中,很难跨越行(或者至少它是你必须要做的事情)。当然,你需要弄清楚如何应对年度障碍;如果我是你,我会将日期保留为实际日期,并使用INTCK
来确定几周内的差异。
如果你确实想要整个ID的最小值,那么数据步骤解决方案(不像SQL解决方案那样整洁,但工作方式大致相同):
data want;
set have;
by id start;
retain _initial_start;
if first.id then _initial_start=start;
weeksincestart=listen-_initial_start; *or whatever you intended - this does not seem right;
drop _initial_start;
run;