楼主: jingju11
2383 15

A tricky data manipulation [推广有奖]

已卖:379份资源

院士

30%

还不是VIP/贵宾

-

威望
3
论坛币
10965 个
通用积分
5.0866
学术水平
452 点
热心指数
463 点
信用等级
347 点
经验
76439 点
帖子
1937
精华
1
在线时间
3428 小时
注册时间
2009-5-22
最后登录
2020-1-26

楼主
jingju11 发表于 2013-1-17 00:39:02 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
数据抽象如下:
data have;
_obs ++1;
input id dt :date9.;
format dt date9.;
cards;
0 31oct2011
1 31jan2010
1 30apr2010
1 31oct2010
1 31jan2011
1 30apr2011
1 31jul2011
1 31jan2012
2 31jan2010
2 31jan2011
2 30apr2011
2 31oct2011
3 31oct2011
;
问题是:

数据按照季度更新(每三个月的最后一天).数据已经按照ID和DT顺序排列.注意:每三个月的更新叫做连续更新.
要求是:
1.如果某个ID里,有至少一个三个或以上连续更新的数据(比如ID=1,从31OCT2010到31JUL2011的连续4次更新),那取出第一个连续更新的前三个记录(只需要这连续排列的前三个记录)--如ID=1所示;
2.如果三个或以上的连续记录不存在,取第一个有连续两个更新的记录--如ID=2所示.
3.否则,去掉该ID--如ID=0和3所示.
问题的来源是:我们只需要这样的数据来做模型.

另外请不要经常SORT数据.因为我们的实际数据大概是一百万的ID,每个ID的可能更新次数从1到1000.数据包含大概50个变量.

京剧

结果 results:

Obs _obs id dt
1   4    1 31OCT2010
2   5    1 31JAN2011
3   6    1 30APR2011
4  10    2 31JAN2011
5  11    2 30APR2011

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:manipulation ulation tricky Trick ATION

已有 2 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
Imasasor + 80 + 80 + 2 + 2 + 2 精彩帖子
webgu + 1 + 1 + 1 精彩帖子

总评分: 经验 + 80  论坛币 + 80  学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

沙发
pobel 在职认证  发表于 2013-1-17 09:44:43
Try this:
  1. data _null_;
  2.     set have end=last;
  3.         by id dt;
  4.         _qtr=qtr(dt)+year(dt)*4;
  5.         length _obs_need $20 _haha $200;
  6.         retain _maxcon _obs_need _haha;

  7.         *** Order consecutive records;
  8.         _lagqtr=lag(_qtr);
  9.         if first.id then do;
  10.                                call missing(_obs_need,_maxcon,_lagqtr);
  11.                   _con=0;
  12.                 end;
  13.         if _qtr-_lagqtr=1 then _con+1;
  14.         else _con=1;

  15.         *** Get the _obs for the first 3(or 2) consecutive records.;
  16.         if _con=2 then do;
  17.                 if missing(_maxcon) then _obs_need=catx(",",_obs-1,_obs);
  18.             if missing(_maxcon) then _maxcon=2;
  19.                 _currid=id;
  20.         end;                     
  21.         if _con=3 then do;
  22.                 if _maxcon ne 3 then _obs_need=catx(",",_obs-2,_obs-1,_obs);
  23.                 _maxcon=3;
  24.         end;

  25.         *** Get the needed observations;
  26.         if last.id and ^missing(_obs_need) then _haha=catx(",",_haha,_obs_need);
  27.         if last then call symputx("_haha",_haha);
  28. run;

  29. data wanted;
  30.     set have;
  31.         if _n_ in (&_haha);
  32. run;
  33.        
复制代码
已有 2 人评分学术水平 热心指数 信用等级 收起 理由
webgu + 1 + 1 + 1 精彩帖子
jingju11 + 2 + 5 + 3 热心帮助其他会员

总评分: 学术水平 + 3  热心指数 + 6  信用等级 + 4   查看全部评分

和谐拯救危机

藤椅
jingju11 发表于 2013-1-17 10:22:07
pobel 发表于 2013-1-17 09:44
Try this:
very smart code.
let‘s say, records from 10,000 to 19,999, you need a length of mv about 10000*5+10000-1 =59999. in fact,i have about 4,800,000 records, not considering more upcoming records with the next update.
京剧

板凳
playmore 发表于 2013-1-17 10:22:35
pobel 发表于 2013-1-17 09:44
Try this:
大概看明白了
能不能先求两个Lead
然后每个观测在三个日期变量上做判断
导出符合条件的观测就好了,即时间间隔各差3个月
这里唯一体现复杂度的就是求两个Lead吧
在SAS里没有Lead函数,只能有proc expand,速度好像不快
playmore邀请您访问ChinaTeX论坛!!!进入ChinaTeX论坛

报纸
jingju11 发表于 2013-1-17 10:29:47
playmore 发表于 2013-1-17 10:22
大概看明白了
能不能先求两个Lead
然后每个观测在三个日期变量上做判断
what do you mean "lead"?

地板
pobel 在职认证  发表于 2013-1-17 10:35:00
jingju11 发表于 2013-1-17 10:22
very smart code.
let‘s say, records from 10,000 to 19,999, you need a length of mv about 10000 ...
If the macro-variable way is not doable, you can generate a dataset with one variable "_obs" which contains the number of observation you need. Then merge it back to the original dataset by _obs.

That is, at the last.id, output the needed obs to the variable _obs. (It's easy for you to do that.)

Hope you know what I mean.
和谐拯救危机

7
jingju11 发表于 2013-1-17 10:55:05
ic.
...
if last.id then do i =1 by 1 while(scan(_haha, i,',') ne '');
_obs = input(scan(_haha,i,','), best.); output;
end;
....
Sounds good. Thanks, JingJu

8
playmore 发表于 2013-1-17 13:11:59
jingju11 发表于 2013-1-17 10:29
what do you mean "lead"?
与lag相对的
SAS只有lag函数
而没有lead函数
playmore邀请您访问ChinaTeX论坛!!!进入ChinaTeX论坛

9
playmore 发表于 2013-1-17 13:15:27
pobel 发表于 2013-1-17 10:35
If the macro-variable way is not doable, you can generate a dataset with one variable "_obs" which ...
嗯,很好的办法

我现在写宏,一般有两种参数,ByFactors和OrderFactors,分别用于by子句和order子句
若初始设置为空的话,则会临时生成这两个变量
这在一些需要变量顺序保持一致的过程,如surveyselect中比较重要
已有 1 人评分学术水平 热心指数 收起 理由
jingju11 + 1 + 5 热心帮助其他会员

总评分: 学术水平 + 1  热心指数 + 5   查看全部评分

playmore邀请您访问ChinaTeX论坛!!!进入ChinaTeX论坛

10
jingju11 发表于 2013-1-19 08:27:23
Thank Pobel again. To fit my code, i did some minor adjustment. To my surprise, there is no optimal way to output selected observation numbers from a large data sets. it costs me about 17 minutes to finish a 500M data set.
jingju

data null_1(drop =_:)
null_2(keep =_x rename =(_x =n_obs));
set rate_all2nonRrr1;
by clnt_no acct_ref_no;
n_obs ++1;
_qtr=qtr(qtr_dt)+year(qtr_dt)*4;
length _obs_need $32;
retain _maxcon _obs_need;
*** Order consecutive records;
_lagqtr=lag(_qtr);
if first.acct_ref_no then call missing(_obs_need,_maxcon,_lagqtr,_con);
if _qtr-_lagqtr =1 then _con +1;
else _con =1;
*** Get the n_obs for the first 3(or 2) consecutive records.;
if _con =2 then do;
if missing(_maxcon) then _obs_need=catx(",",n_obs-1,n_obs);
if missing(_maxcon) then _maxcon=2;
end;
if _con=3 then do;
if _maxcon ne 3 then _obs_need=catx(",",n_obs-2,n_obs-1,n_obs);
_maxcon=3;
end;
output null_1;
*** Get the needed observations;
if last.acct_ref_no then do i =1 by 1 while (scan(_obs_need,i,',') ^=' ');
_x =input(scan(_obs_need,i,','), best.);
output null_2;
end;
run;
proc sql;
create table null_3 as
select a.*
from
null_1 as a
inner join
null_2 as b
on a.n_obs =b.n_obs;
quit;


您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-15 06:37