2、生成新的字段 dh dh(t)=median(p(t)~p(t-2)) 即,对每个code 在每个日期(date),对应一个dh(t) 它是该code临近的三天的p的中位数。
注意:上述的计算在code之间不能交叉。
那位高人能出手帮忙,在下感激不尽!
由 specialuse » 2009年 7月 8日 周三 10:19 am
最大最小值的一问,我倒是有了一个解决的办法(我的办法很土,也望高人再指点);但是median的一问还望高人指点一下啊
由 hopewell » 2009年 7月 8日 周三 2:58 pm
看看是这样吗?
data aaa;
input code date $ p;
datalines;
1 1-1 1.1
1 1-2 1.2
1 1-3 1.1
1 1-4 1.5
1 1-5 1.7
2 1-1 2.1
2 1-2 2.2
2 1-3 1.6
2 1-4 1.5
2 1-5 1.9
3 1-1 1.3
3 1-2 1.4
3 1-3 1.6
3 1-4 1.1
3 1-5 1.0
;
data bbb (drop=n);
set aaa;
by code;
if first.code then n=1;
else n+1;
cmp=max(p,lag1(p),lag2(p))-min(p,lag1(p),lag2(p));
dh=median(p,lag1(p),lag2(p));
if n lt 3 then call missing(cmp,dh);/*小于3项的时候缺失化*/
run;
由 specialuse » 2009年 7月 8日 周三 5:13 pm
十分感谢hopewell兄,就是这个意思。但我在上面列的数据集是一个样例,处理的实际数据比较大,求中值和最值时面临的样本区间也比较长(比如是一个100日的移动窗口),代码能扩展一下解决这个问题么?
由 hopewell » 2009年 7月 8日 周三 11:51 pm
不知道效率如何?还有更好的方法吗?
/* 设定滞后量 */
%let lag_n=10;
/* 创建模拟数据 */
data raw_data;
do code=1 to 100;
do date='01jan09'd to '30jan09'd;
p=ceil(10*ranuni(123));
output;
end;
end;
format date yymmdd10.;
run;
/* 拷贝模拟数据 */
data copy_data;
set raw_data;
rename code=copy_code
date=copy_date
p=copy_p
;
run;
/* 使用HASH ITERATOR创建中间变量 hashexp:10hash表的框数*/
/*
http://wenku.baidu.com/view/3a067cc7aa00b52acfc7cacf.html相关框数资料*/
data temp_data(drop=copy_code copy_date copy_p rc);
if _n_=1 then
do;
declare hash p_hash(dataset:'copy_data',hashexp:10,ordered:'ascending');
p_hash.definekey ('copy_code','copy_date');
p_hash.definedata('copy_code','copy_date','copy_p');
p_hash.definedone();
call missing(copy_code,copy_date,copy_p);
declare hiter p_hiter('p_hash');
end;
set raw_data;
length temp $500;
flag=0;
rc=p_hiter.first();
do while(rc eq 0);
if (code=copy_code) and (0<=date-copy_date<&lag_n) then
do;
if flag=0 then temp=cat(copy_p);
else temp=catx(',',temp,copy_p);
flag+1;
end;
rc=p_hiter.next();
end;
run;
/* 创建宏 */
%macro compute;
%let dsid=%sysfunc(open(temp_data));
%let nobs=%sysfunc(attrn(&dsid,nobs));
%syscall set(dsid);
%do i=1 %to &nobs;
%let rc=%sysfunc(fetchobs(&dsid,&i));
code=&code;
date=&date;
p=&p;
%if &flag=&lag_n %then %do;
cmp=max(&temp)-min(&temp);
dh=median(&temp);
%end;
output;
%end;
%let dsid=%sysfunc(close(&dsid));
%mend;
/* 调用宏 */
data final_data;
%compute
format date yymmdd10.;
run;
由 徐福贵 » 2009年 7月 9日 周四 7:21 am
搞不懂楼主想要什么,但是楼上的宏让人敬仰,拜师之意油然而生。
由 hopewell » 2009年 7月 9日 周四 9:54 am
这段程序确实效率高!
有些地方没看懂,请教徐福贵一下:
1 set语句放在do组里之后,对数据集观测的读取顺序会有什么影响?
2 是因为do until先执行后判断,所以才能把by语句放到do组中的吗(即先有last.code,后有by语句)?
谢谢!
data final_data2(drop=index);
array pp[0:%eval(&lag_n-1)] _temporary_; /* 创建数组,下标0-9 */
index = 0; /* 为下标变量赋初值 */
/* 把set语句用在do组中,我还是头次见 */
do _n_=1 by 1 until(last.code); /* 在每个code组中循环 */
set raw_data; /* ??? */
by code; /* ??? */
pp[index] = p; /* 为数组元素赋p值 */
index = mod(index+1, &lag_n); /* 下标变量+1,取模保证值域为0-9 */
/* 计算部分 */
if _n_>=&lag_n then do;
cmp = max(of pp
) - min(of pp);
dh = median(of pp);
end;
output;
end;
run;
由 徐福贵 » 2009年 7月 9日 周四 12:26 pm
我也不知道怎么解释,我最想做的是拜您为师,
题外话,我还想找个老伴,我看维族人民英雄Rabiye Qadir不错, 可惜她家的老头子还没不致哪天死,就算死了也不知道看不看得上我一个泥巴腿子,让我没个盼头。家珍一定不会怪我的,她只会为我这向上的念头在墓中激赏不已!
由 hopewell » 2009年 7月 9日 周四 9:27 pm
生活真不美好,一觉醒来猛然发现DO循环已不副当初的模样...
SAS到底该怎么学呀?
由 specialuse » 2009年 7月 10日 周五 11:52 am
这里高手真多,谢谢大家
由 gzgoon » 2009年 7月 10日 周五 4:02 pm
the codes of Xu and Hopewell dont seem to solve the problem, but they are indeed quite subtle!!!
由 gzgoon » 2009年 7月 10日 周五 4:09 pm
sorry for my last reply. codes of Xu and Hopewell work very well. i am sorry
由 hopewell » 2009年 7月 10日 周五 4:18 pm
总算貌似看懂徐福贵的程序了,能写成这样真是太神奇了
如果我理解的不对,望指点,谢谢.
data final_data2(drop=index pp:);
/* before break-event */
array pp[0:%eval(&lag_n-1)] pp0-pp9; /* 声明数组 */
index = 0; /* 在每个do组开始前将数组下标变量置为0 */
/* nested do loop */
/* 对数据集观测的读入输出均在do-loop中,implied Data step loop仅起到赋初值的作用 */
/* 在每次do-loop的一次循环中仅将当前记录的p值赋予数组中的相应下标的元素,充分利用变量值在PDV中的retain特性 */
/* 示意:
obs p |pp0 pp1 pp2 pp3 pp4 pp5 pp6 pp7 pp8 pp9
-----------------------------------------------
0 8 |(8) . . . . . . . . .
1 4 | 8 (4) . . . . . . . .
2 2 | 8 4 (2) . . . . . . .
3 10 | 8 4 2 (10) . . . . . .
4 4 | 8 4 2 10 (4) . . . . .
5 3 | 8 4 2 10 4 (3) . . . .
6 8 | 8 4 2 10 4 3 (8) . . .
7 4 | 8 4 2 10 4 3 8 (4) . .
8 2 | 8 4 2 10 4 3 8 4 (2) .
9 2 | 8 4 2 10 4 3 8 4 2 (2)
-----------------------------------------------
10 8 |(8) 4 2 10 4 3 8 4 2 2
11 5 | 8 (5) 2 10 4 3 8 4 2 2
12 10 | 8 5 (10) 10 4 3 8 4 2 2
13 3 | 8 5 10 (3) 4 3 8 4 2 2
14 8 | 8 5 10 3 (8) 3 8 4 2 2
15 6 | 8 5 10 3 8 (6) 8 4 2 2
16 6 | 8 5 10 3 8 6 (6) 4 2 2
17 9 | 8 5 10 3 8 6 6 (9) 2 2
18 2 | 8 5 10 3 8 6 6 9 (2) 2
19 9 | 8 5 10 3 8 6 6 9 2 (9)
*/
do _n_=1 by 1 until(last.code); /* 使用dow-loop */
set raw_data;
by code;
pp[index] = p; /* 根据下标变量为数组赋值 */
index = mod(index+1, &lag_n); /* 改变下标变量的值,当读第11、21、31...条记录时index=0(初值为0) */
if _n_>=&lag_n then do; /* 计算部分 */
cmp = max(of pp) - min(of pp);
dh = median(of pp);
end;
output; /* 在do-loop的每次循环结束后输出观测 */
end;
/* after break-event */
/* 取消了隐含的outout语句 */
run;