给定ID的最小值

时间:2013-08-04 19:22:17

标签: sas

我的数据按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语句”

3 个答案:

答案 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;