SAS:如何过滤最接近月份最后一天的(多个)条目(每个月)
SAS: How can I filter for (multiple) entries which are closest to the last day of month (for each month)
我有一个很大的数据集,我想对每个月的日期条目最接近该月最后一天的所有行进行过滤。因此,最接近一个月最后一天的那一天可能有多个条目。
例如:
原始数据集
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 进行研究。
1) 创建一个新变量 periode = put(date,yymmn6.) /* 给你 yyyymm*/
2) 按周期和日期对 table 进行排序
3) 现在 periode.last 逻辑将 select 您需要的每个周期的记录。
类似...
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;
您可以使用两个名为 intnx
和 intck
的 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()
按时间间隔调整日期。在上面的例子中,使用的四个参数是:
- 你想要 add/subrate 间隔的大小 'step'。
- 被引用的日期
- 要进行多少间隔步骤
- 如何 'round' 步骤(例如将其四舍五入到结果 day/week/year 的 start/end/middle)
Intck()
简单计算两个日期之间的间隔步数
这将为您提供最接近月底的那一天的所有记录
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
;
如果取消注释,实际使用的过滤器会显示在输出中 table。
将需求与解决方案进行比较:
proc compare base=work.want compare=work.solution;
结果
NOTE: No unequal values were found. All values compared are exactly equal.
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
我有一个很大的数据集,我想对每个月的日期条目最接近该月最后一天的所有行进行过滤。因此,最接近一个月最后一天的那一天可能有多个条目。
例如: 原始数据集
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 进行研究。
1) 创建一个新变量 periode = put(date,yymmn6.) /* 给你 yyyymm*/ 2) 按周期和日期对 table 进行排序 3) 现在 periode.last 逻辑将 select 您需要的每个周期的记录。
类似...
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;
您可以使用两个名为 intnx
和 intck
的 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()
按时间间隔调整日期。在上面的例子中,使用的四个参数是:
- 你想要 add/subrate 间隔的大小 'step'。
- 被引用的日期
- 要进行多少间隔步骤
- 如何 'round' 步骤(例如将其四舍五入到结果 day/week/year 的 start/end/middle)
Intck()
简单计算两个日期之间的间隔步数
这将为您提供最接近月底的那一天的所有记录
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
;
如果取消注释,实际使用的过滤器会显示在输出中 table。
将需求与解决方案进行比较:
proc compare base=work.want compare=work.solution;
结果
NOTE: No unequal values were found. All values compared are exactly equal.
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