楼主: wdxmahone
8755 16

sas取前100行的最小值 [推广有奖]

11
bobguy 发表于 2011-7-23 11:08:21
wdxmahone 发表于 2011-7-22 16:13
各位大侠,我想取前100行的最小值,怎么实现。可以考虑以下测试数据。x1 x2
01 1
01 2
01 1
01 4
01 5
02 1
02 -3
02 3
02 4
02 5
;
X1是分组变量,我想取X2的每个分组变量前三行的最小值。
我用sql的group by做,但是由于数据量很大,要循环几千次,相当慢,不知道各位大侠有什么好的办法。谢哈~~
IT WORKS ON 3 ROWS. IT SHOULD WORK FOR 100 ROWS. BUT I AM NOT SURE ABOUT ITS PEFORMANCE.

ALSO THE LOGIC FOR THE FIRST AND THE SECOND OBS IN A GROUP IS LIGHTLY DIFFERENT. IT RETURNS THE MINIMUN UPTO 3 ROWS.

data test;
RETAIN G '  ';
input x1 $ x2;
IF G NE X1 THEN DO;
   G=X1;
   ID=0;
END;
ID+1;
datalines;
01 1
01 2
01 1
01 4
01 5
02 1
02 -3
02 3
02 4
02 5
;
PROC SQL;
  SELECT DISTINCT A.X1, A.ID ,A.X2, MIN(B.X2) AS MIN
  FROM TEST AS A
   JOIN TEST AS B
  ON
   A.X1=B.X1
  AND
  (A.ID-B.ID= 0 OR A.ID-B.ID= 1 OR A.ID-B.ID= 2)
  GROUP BY A.X1, A.ID
  ORDER BY A.X1, A.ID
;
QUIT;

                               x1              ID        x2       MIN
                                ƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒƒ
                                01               1         1         1
                                01               2         2         1
                                01               3         1         1
                                01               4         4         1
                                01               5         5         1
                                02               1         1         1
                                02               2        -3        -3
                                02               3         3        -3
                                02               4         4        -3
                                02               5         5         3
已有 1 人评分学术水平 热心指数 收起 理由
wdxmahone + 1 + 1 很棒

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

12
wdxmahone 发表于 2011-7-23 12:44:39
11# bobguy 非常好,谢哈!

13
wdxmahone 发表于 2011-7-23 12:49:02
6# pobel
这个的结果相当于取前面所有行的最小值

14
wdxmahone 发表于 2011-7-23 12:51:33
这个好像不太好应用在100行
yugao1986 发表于 2011-7-22 17:26
  1. DATA a;
  2.   INPUT x1 x2;
  3.   m=lag(x2);
  4.   n=lag(m);
  5.   DATALINES;
  6. 01 1
  7. 01 2
  8. 01 1
  9. 01 4
  10. 01 5
  11. 02 1
  12. 02 -3
  13. 02 3
  14. 02 4
  15. 02 5
  16. ;
  17. data b(keep=x1 x2 x3);
  18.    set a;
  19.    by x1;
  20.    retain x3 l;
  21.    if first.x1 then call missing(x3);
  22.       else x3=min(x2,m,n);
  23.    l=lag(x3);
  24.    if l=. then x3=.;
  25. run;
  26. proc print;run;
复制代码

15
wdxmahone 发表于 2011-7-25 10:33:34
您好,有没有比较快的方法啊,我的数据集有几百万行,而且是取每一行前200多行的数,计算相当慢,即使在服务器上计算也得几十分钟呢!谢哈~~
bobguy 发表于 2011-7-23 11:08
wdxmahone 发表于 2011-7-22 16:13
各位大侠,我想取前100行的最小值,怎么实现。可以考虑以下测试数据。x1 x2
01 1
01 2
01 1
01 4
01 5
02 1
02 -3
02 3
02 4
02 5
;
X1是分组变量,我想取X2的每个分组变量前三行的最小值。
我用sql的group by做,但是由于数据量很大,要循环几千次,相当慢,不知道各位大侠有什么好的办法。谢哈~~
IT WORKS ON 3 ROWS. IT SHOULD WORK FOR 100 ROWS. BUT I AM NOT SURE ABOUT ITS PEFORMANCE.

ALSO THE LOGIC FOR THE FIRST AND THE SECOND OBS IN A GROUP IS LIGHTLY DIFFERENT. IT RETURNS THE MINIMUN UPTO 3 ROWS.

data test;
RETAIN G '  ';
input x1 $ x2;
IF G NE X1 THEN DO;
   G=X1;
   ID=0;
END;
ID+1;
datalines;
01 1
01 2
01 1
01 4
01 5
02 1
02 -3
02 3
02 4
02 5
;
PROC SQL;
  SELECT DISTINCT A.X1, A.ID ,A.X2, MIN(B.X2) AS MIN
  FROM TEST AS A
   JOIN TEST AS B
  ON
   A.X1=B.X1
  AND
  (A.ID-B.ID= 0 OR A.ID-B.ID= 1 OR A.ID-B.ID= 2)
  GROUP BY A.X1, A.ID
  ORDER BY A.X1, A.ID
;
QUIT;

                               x1              ID        x2       MIN
                                ??????????????????????????????????????
                                01               1         1         1
                                01               2         2         1
                                01               3         1         1
                                01               4         4         1
                                01               5         5         1
                                02               1         1         1
                                02               2        -3        -3
                                02               3         3        -3
                                02               4         4        -3
                                02               5         5         3

16
soporaeternus 发表于 2011-7-25 11:27:46
这个问题之前讨论过,临时数组做吧
Let them be hard, but never unjust

17
bobguy 发表于 2011-7-26 10:58:47
wdxmahone 发表于 2011-7-25 10:33
您好,有没有比较快的方法啊,我的数据集有几百万行,而且是取每一行前200多行的数,计算相当慢,即使在服务器上计算也得几十分钟呢!谢哈~~
bobguy 发表于 2011-7-23 11:08
wdxmahone 发表于 2011-7-22 16:13
各位大侠,我想取前100行的最小值,怎么实现。可以考虑以下测试数据。x1 x2
01 1
01 2
01 1
01 4
01 5
02 1
02 -3
02 3
02 4
02 5
;
X1是分组变量,我想取X2的每个分组变量前三行的最小值。
我用sql的group by做,但是由于数据量很大,要循环几千次,相当慢,不知道各位大侠有什么好的办法。谢哈~~
IT WORKS ON 3 ROWS. IT SHOULD WORK FOR 100 ROWS. BUT I AM NOT SURE ABOUT ITS PEFORMANCE.

ALSO THE LOGIC FOR THE FIRST AND THE SECOND OBS IN A GROUP IS LIGHTLY DIFFERENT. IT RETURNS THE MINIMUN UPTO 3 ROWS.

data test;
RETAIN G '  ';
input x1 $ x2;
IF G NE X1 THEN DO;
   G=X1;
   ID=0;
END;
ID+1;
datalines;
01 1
01 2
01 1
01 4
01 5
02 1
02 -3
02 3
02 4
02 5
;
PROC SQL;
  SELECT DISTINCT A.X1, A.ID ,A.X2, MIN(B.X2) AS MIN
  FROM TEST AS A
   JOIN TEST AS B
  ON
   A.X1=B.X1
  AND
  (A.ID-B.ID= 0 OR A.ID-B.ID= 1 OR A.ID-B.ID= 2)
  GROUP BY A.X1, A.ID
  ORDER BY A.X1, A.ID
;
QUIT;

                               x1              ID        x2       MIN
                                ??????????????????????????????????????
                                01               1         1         1
                                01               2         2         1
                                01               3         1         1
                                01               4         4         1
                                01               5         5         1
                                02               1         1         1
                                02               2        -3        -3
                                02               3         3        -3
                                02               4         4        -3
                                02               5         5         3
As I said before, SQL may have performance issues because it involves a kind of cartisian joint.

Below is a data step approach. With 20000 group , maximum 1000 obs in each group and total obs of 10 millions . It takes 75 seconds on a I5 chip think pad. BTY, the cpu time is linear in number of K. That is a good thing.


879  %let group=20000;
880  %let maxn=1000;
881
882  %let k=100;
883
884  data t1;
885     do g=1 to &group;
886          n=ceil(ranuni(123)*&maxn);
887          do i=1 to n;
888          x=ceil(rannor(123)*&maxn);
889          output;
890          end;
891      end;
892      keep g x;
893  run;
NOTE: The data set WORK.T1 has 10053753 observations and 2 variables.
NOTE: DATA statement used (Total process time):
      real time           2.04 seconds
      cpu time            2.04 seconds

894
895  data t2;
896    array tmpx(10000) _temporary_ ;
897    array tmpy(&k) _temporary_ ;
898
899   do until(last.g);
900     set t1;
901     by g;
902     if first.g then cnt=0;
903     cnt+1 ;
904     tmpx[cnt]=x;
905     k=0;
906     do i=1 to &k;
907       tmpy=1e308;
908     end;
909     do i=max(cnt-&k+1,1) to cnt;
910       k+1;
911       tmpy[k]=tmpx;
912       *put tmpy[k]=;
913     end;
914     call sortn(of tmpy );
915     min=tmpy[1];
916     output;
917   end;
918   keep x g min;
919   run;
NOTE: There were 10053753 observations read from the data set WORK.T1.
NOTE: The data set WORK.T2 has 10053753 observations and 3 variables.
NOTE: DATA statement used (Total process time):
      real time           1:15.28
      cpu time            1:15.14

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

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