楼主: cz851218
7429 37

连续时间段里面的最值 [推广有奖]

11
crackman 发表于 2010-5-10 17:21:33
4# nkwilling
很厉害,point玩得如此熟练

12
crackman 发表于 2010-5-10 17:22:06
5# soporaeternus
写的很不错
值得学习

13
crackman 发表于 2010-5-10 17:54:20
4# nkwilling
为了更多的初学者能读懂牛人的代码,我来翻译一下,就如soporaeternus 哥们说的,第三类人,翻译人员
data a; /*创建数据集A*/
input x @@;
cards;
2 5 6 9 8 2 6 5 4 7 9 5 6 7
;
run;
data aa; /*创建数据集AA,变量换名为X1*/
set a;
rename x=x1;
run;
data b;
DO row=5 TO 14; /*外循环,外循环每执行一次,内循环执行5次*/
set a point=row; /*复制指定的观测,ROW=5时说复制数据集A中的第五条观测对象的X的变量值*/
   do col=row-4 to row; /*内循环,同样建立一个指针变量COL*/
      set aa point=col; /*从指定的变量COL的值处取AA中指定的观测对象的X1的变量值,例如当COL=1的时候,就复制AA数据集中第一个条观测*/
          retain xxx xx;/*初始化变量XXX XX*/
          xx=max(x1,x);/*当第一次内循环时,也就是COL=1时,从AA取出的X1的第一条观测值和外循环取出的X的第五条观测值进行比较大小,并将较大值赋值给XX*/
          xxx=max(xxx,xx); /*比较XXX XX,将值大者赋值给XXX*/
          put xx= @; /*在LOG输出XX. XXX X1 X*/
          put xxx= @;
          put x1= @;
          put x=;
   end; /*结束一次内循环*/
output;
xxx=0; /*XXX值清0*/
put xxx=; /*输出XXX*/
END; /*结束外循环*/
stop; /*结束循环程序*/
keep xxx; /*结果数据集保留XXX变量*/
run;
大家如何还是不能理解可以这样等价来看:
xx=8 xxx=8 x1=2 x=8  row=5 col=1
xx=8 xxx=8 x1=5 x=8  row=5 col=2
xx=8 xxx=8 x1=6 x=8  row=5 col=3
xx=9 xxx=9 x1=9 x=8  row=5 col=4
xx=8 xxx=9 x1=8 x=8  row=5 col=5
xxx=0
xx=5 xxx=5 x1=5 x=2  row=6 col=1
xx=6 xxx=6 x1=6 x=2 row=6col=2
xx=9 xxx=9 x1=9 x=2 row=6 col=3
xx=8 xxx=9 x1=8 x=2 row=6 col=4
xx=2 xxx=9 x1=2 x=2 row=6 col=5
xxx=0
xx=6 xxx=6 x1=6 x=6
xx=9 xxx=9 x1=9 x=6
xx=8 xxx=9 x1=8 x=6
xx=6 xxx=9 x1=2 x=6
xx=6 xxx=9 x1=6 x=6
xxx=0
xx=9 xxx=9 x1=9 x=5
xx=8 xxx=9 x1=8 x=5
xx=5 xxx=9 x1=2 x=5
xx=6 xxx=9 x1=6 x=5
xx=5 xxx=9 x1=5 x=5
xxx=0
xx=8 xxx=8 x1=8 x=4
xx=4 xxx=8 x1=2 x=4
xx=6 xxx=8 x1=6 x=4
xx=5 xxx=8 x1=5 x=4
xx=4 xxx=8 x1=4 x=4
xxx=0
xx=7 xxx=7 x1=2 x=7
xx=7 xxx=7 x1=6 x=7
xx=7 xxx=7 x1=5 x=7
xx=7 xxx=7 x1=4 x=7
xx=7 xxx=7 x1=7 x=7
xxx=0
xx=9 xxx=9 x1=6 x=9
xx=9 xxx=9 x1=5 x=9
xx=9 xxx=9 x1=4 x=9
xx=9 xxx=9 x1=7 x=9
xx=9 xxx=9 x1=9 x=9
xxx=0
xx=5 xxx=5 x1=5 x=5
xx=5 xxx=5 x1=4 x=5
xx=7 xxx=7 x1=7 x=5
xx=9 xxx=9 x1=9 x=5
xx=5 xxx=9 x1=5 x=5
xxx=0
xx=6 xxx=6 x1=4 x=6
xx=7 xxx=7 x1=7 x=6
xx=9 xxx=9 x1=9 x=6
xx=6 xxx=9 x1=5 x=6
xx=6 xxx=9 x1=6 x=6
xxx=0
xx=7 xxx=7 x1=7 x=7
xx=9 xxx=9 x1=9 x=7
xx=7 xxx=9 x1=5 x=7
xx=7 xxx=9 x1=6 x=7
xx=7 xxx=9 x1=7 x=7
xxx=0

14
crackman 发表于 2010-5-10 19:17:03
5# soporaeternus
这个哥们写的程序很有其他程序代码的风格,很不错,确实很值得学习
  • %MACRO T(n);
  • data b;
  •         retain t0-t%eval(&n-1) 0;/*初始化变量t0-t4,假设n=5*/
  •         set a;
  •        %do i=%eval(&n-1) %to 1 %by -1;
  •                 t&i=t%eval(&i-1);
  •         %end; /*这点我很欣赏,有点类似于一个队列一样,当SET 复制指针从1---14,每读取一个,然后看看T0-T4的变化,像一个队列,不断的进入从最低端往上冒*/
  •         t0=x;
  •         max=max(of t0-t%eval(&n-1));
  •         dis=max(0*((t0-max)=0)%do i=1 %to %eval(&n-1) %by 1;,&i*((t&i-max)=0)%end;);  /*这一句有点难理解,用了一个宏循环来重复实现MAX函数的后一个比较数,这点类似在其他编程里面,像用一个函数得出一个返回值,用这个返回值作为MAX函数的另外一个比较数字,这里的宏就是实现了这样的一个功能,不过注意中间的逗号不能丢,因为宏这个时候repeat的是一个语句(,1*((t1-max)=0) 2*((t2-max)=0)........)*/
  • /*        dis=min(0*((t0-max)=0)%do i=1 %to %eval(&n-1) %by 1;,&i*((t&i-max)=0)%end;);*/
  •         keep x max dis;
  • run;
  • %MEND T;
  • %T(5);
已有 1 人评分学术水平 热心指数 收起 理由
soporaeternus + 1 + 1 那个逗号就是这样说...斑竹好热心

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

15
sushe1527 发表于 2010-5-10 21:20:42
擦,来晚了完事了 扔块砖走人~~
data raw;
input a@@;
cards;
2 5 6 9 8 2 6 5 4 7 9 5 6 7
;run;


%macro i(n);
data b;
set raw;
by a notsorted;
array t t1-t&n;
t0=a;
%do i=1 %to &n;
t&i=lag&i(a);
b=max(of t0-t%eval(&n-1));
%end;
keep a b;
run;
data final;
set b;
by b notsorted;
if first.b then c=0;
else c+1;
if first.b then c=b-a;
run;
%mend ;
%i(5);
已有 1 人评分经验 论坛币 学术水平 热心指数 收起 理由
crackman + 100 + 100 + 1 + 1 精彩帖子

总评分: 经验 + 100  论坛币 + 100  学术水平 + 1  热心指数 + 1   查看全部评分

16
yatming 发表于 2010-5-10 21:44:46
有意思,crackman唱完红脸,我来唱白脸,呵呵。
4# nkwilling
第一个就是point的使用有对数据集的限制,连接到关系型数据库的表大多不能使用point,至少到现在我还没遇到哪个数据库是不被限制的,原因就是log中的error,非随机访问。
第二个就是效率问题:海量数据较大情况下,虽然rename和copy可以不用data step,而用proc datasets来提高一点点效率,但是新建表临时表的方式,会使海量数据对存储形成挑战,其次嵌套循环的计算量也不少。

5# soporaeternus
个人认为更值得探讨的是,N个临时变量是否可以采用array _temporary_,这样array变量并不存储在pdv而是直接存储在memory里(虽然pdv也是存储在memory里),但对于N较大情况下,drop的计算量也可以减少一些,还有一点好处是 _temporary_自动retain的。

呵呵,鸡蛋里挑骨头,欢迎拍砖。
已有 1 人评分经验 论坛币 学术水平 热心指数 收起 理由
crackman + 100 + 100 + 1 + 1 我不理解你说的,但是支持你的回答

总评分: 经验 + 100  论坛币 + 100  学术水平 + 1  热心指数 + 1   查看全部评分

17
soporaeternus 发表于 2010-5-10 22:04:23
16# yatming
恩,关键是array我不是很熟.......,不到万不得已坚决不用array......
PDV变量很多的时候,可能在变量的keep或drop flag的处理上浪费资源,这点array 到temp更好,因为它默认不输出。
Let them be hard, but never unjust

18
jingju11 发表于 2010-5-10 22:58:37
  1. DATA x;
  2. INPUT A@@; DATALINES;
  3. 2 5 6 9 8 2 6 5 4 7 9 5 6 7
  4. ;
  5. DATA y;
  6. SET x;
  7. ARRAY A_{5} _TEMPORARY_;
  8. N = MOD(_N_, 5); IF NOT N THEN N = 5;
  9. A_[N] = A;
  10. B = MAX(OF A_[*]);
  11. DO I = 1 TO 5;
  12.   IF B = A_[I] THEN DO;
  13.    C = IFN(N-I <0, N-I+5, N-I); LEAVE;
  14.   END;
  15. END;
  16. IF _N_ <5 THEN CALL MISSING(B, C);
  17. KEEP A B C;
  18. RUN;
复制代码
已有 1 人评分学术水平 热心指数 收起 理由
醉_清风 + 1 + 1 精彩帖子

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

19
crackman 发表于 2010-5-11 00:28:29
DATA x;
INPUT A@@;
DATALINES;
2 5 6 9 8 2 6 5 4 7 9 5 6 7
;
DATA y;
SET x;
ARRAY A_{5} _TEMPORARY_; /*建立临时数据A_*/
N = MOD(_N_, 5);  /*用自动变量—_n_与5的相除的余数赋值给变量N*/
IF  NOT N THEN N =5; /*这里关键是NOT N=TRUE的意义,因为当_N_与5的余数为0时,就是 NOT 0 即为1也就是TRUE*/
A_[N] = A; /*将从X读取每一个X变量赋值给临时数组A_*/
B = MAX(OF A_
  • ); /*从临时数组A_中取最大值,这里仔细研究,精彩之处也就是此处*/
    put a_[1]=  a_[2]=  a_[3]=  a_[4]=  a_[5]=  B=;  /*为了理解程序,我加的一行,网友好好看看,其实就是相同N时,a_进行替换*/
    DO I = 1 TO 5;
      IF B = A_[I] THEN DO; /*判断最大值时N对应的值*/
       C = IFN(N-I <0, N-I+5, N-I);  /*相当于if n-I<0 then c=n-I+5;else c=N-I;*/
      LEAVE;
      END;
    END;
    IF _N_ <5 THEN CALL MISSING(B, C); /*相当于IF _N_<5 then b=c=.;*/
    RUN;
  • 已有 1 人评分学术水平 热心指数 收起 理由
    醉_清风 + 1 + 1 版主很热心

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

    20
    cz851218 发表于 2010-5-11 09:11:57
    5# soporaeternus

    您的程序正好,太感谢您了!!

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

    本版微信群
    加好友,备注cda
    拉您进交流群
    GMT+8, 2025-12-31 20:57