【问题标题】:SAS: How can I filter for (multiple) entries which are closest to the last day of month (for each month)SAS:如何过滤最接近每月最后一天的(多个)条目(每个月)
【发布时间】:2015-06-04 21:41:57
【问题描述】:

我有一个很大的数据集,并希望为每个月的日期条目最接近该月最后一天的所有行过滤它。因此,最接近每月最后一天的那一天可能有多个条目。

例如: 原始数据集

date          price       name
05-01-1995    1,2         abc
06-01-1995    1,5         def
07-01-1995    1,8         ghi
07-01-1995    1,7         mmm
04-02-1995    1,9         jkl
27-02-1995    2,1         mno

目标:

date          price       name
07-01-1995    1,8         ghi
07-01-1995    1,7         mmm
27-02-1995    2,1         mno

我有 2 个想法,但在 SAS 中的循环(用于遍历几个月)内实现它失败了。 1.idea:创建新列,指示当前月的最后一天(intnx() 函数);然后过滤最接近该月最后一天的所有条目:

date          price       name   last_day_of_month
05-01-1995    1,2         abc    31-01-1995
06-01-1995    1,5         def    31-01-1995
07-01-1995    1,8         ghi    31-01-1995
04-02-1995    1,9         jkl    28-02-1995
27-02-1995    2,1         mno    28-02-1995

2.idea:简单地过滤每个月具有最高日期的条目(可能使用 max 函数?!)

如果您能帮助我,我将非常高兴,因为我已经习惯了普通的编程语言,并且刚开始使用 SAS 进行研究。

【问题讨论】:

  • 这个问题和By group processing in SAS的问题很相似。
  • 请注意,您必须将原始数据集按日期降序排列,以使其与已接受的副本答案中的解决方案一起使用。
  • 感谢您链接到类似问题。我还有一个问题:如何调整解决方案,所以我不仅得到每个月的最后一个条目,而且得到最接近月底的所有条目(我编辑了问题。例如:最后两个条目一个月是 27 号,那么我想得到这两个条目)
  • 一个控制问题,你确定你也不想在name上分组吗?
  • 不,这对我来说并不重要。

标签: loops date filter sas


【解决方案1】:

proc sql 是解决这种情况的一种方法。我将分解您的原始要求,并在sql 中解释如何解释它们。

由于您想group 您的观察日期,您可以使用having 子句过滤每月的max 日期。

data work.have;
input date DDMMYY10. price name $;
format date date9.;
datalines;
05-01-1995    1.2         abc
07-01-1995    1.8         ghi
06-01-1995    1.5         def
07-01-1995    1.7         mmm
04-02-1995    1.9         jkl
27-02-1995    2.1         mno
;

data work.want;
input date DDMMYY10. price name $;
format date date9.;
datalines;
07-01-1995    1.8         ghi
07-01-1995    1.7         mmm
27-02-1995    2.1         mno
;

proc sql ;
create table work.want as
  select *
    /*, max(date) as max_date format=date9.*/
    /*, intnx('month',date,0,'end') as monthend format=date9.*/
  from work.have
  group by intnx('month',date,0,'end')
  having max(date) = date
  order by date, name
;

如果取消注释 cmets,实际使用的过滤器会显示在输出表中。

将需求与解决方案进行比较:

proc compare base=work.want compare=work.solution;

结果

注意:没有发现不相等的值。所有比较的值都完全相同。

【讨论】:

  • 非常感谢您的出色解决方案!
【解决方案2】:

1) 创建一个新变量 periode = put(date,yymmn6.) /* 给你 yyyymm*/ 2)按周期和日期对表格进行排序 3) 现在 periode.last 逻辑将选择每个 periode 所需的记录。

类似...

    data tab2;
      set your_table;
      periode = put(date,yymmn6.);
   run;

   proc sort data= tab2;
     by  periode date;
   run;

   data tab3;
    set tab2;
     by periode;
     if last.periode then output;
   run;

【讨论】:

  • 抱歉,我的问题不够具体。我刚刚编辑了它:我不仅想要每个月的最后一个条目,还想要所有最接近月底的条目(例如:一个月的最后两个条目是在 27 日,那么我想要获得这两个条目)
【解决方案3】:

您可以使用两个称为 intnxintck 的 SAS 函数与 proc sql 一起执行此操作:

proc sql ;
create table want as
  select *, put(date,yymmn6.) as month, intck('days',date,intnx('month',date,0,'end')) as DaysToEnd 
  from have
  group by month
  having (DaysToEnd=min(DaysToEnd))
;quit ;

Intnx() 按间隔调整日期。在上述情况下,使用的四个参数是:

  1. 您要添加/减少间隔的“步长”大小。
  2. 引用的日期
  3. 需要多少间隔步数
  4. 如何“四舍五入”步骤(例如,将其四舍五入到结果日/周/年的开始/结束/中间)

Intck() 只计算两个日期之间的间隔步数

这将为您提供最接近月底日期的所有记录

【讨论】:

  • 抱歉,我的问题不够具体。我刚刚编辑了它:我不仅想要每个月的最后一个条目,还想要所有最接近月底的条目(例如:一个月的最后两个条目是在 27 日,那么我想要获得这两个条目)
  • 没问题 - 只是添加了一个更新来修改 proc sql 以提供多条记录
【解决方案4】:
Another approach is by using proc rank;

data mid;
  retain yrmth date;
  set have;
  format date yymmddn8.;
  yrmth = put(date,yymmn6.);
run;

proc sort data = mid;
  by yrmth descending date;
run;

proc rank data = mid out = want descending  ties=low;
by yrmth;
var date;
ranks rankdt;
run;

data want1;
  set want;
  where rankdt = 1;
run;

HTH

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 2020-03-20
    • 1970-01-01
    相关资源
    最近更新 更多