[問題] SAS 取每個ID前三筆觀測直

昨天遇到一個有趣的題目,放上來與各位分享

讀者也可以想想程式怎麼寫

參考答案不是唯一解

先看手上的資料(檔案test)

data test;
  input id $ value;
  cards;
01 123
01 456
01 789
01 112
01 321
02 654
02 987
02 753
02 159
;
run;

每個ID都不單純只有一筆觀測值

現在想要取每個ID的前三筆數值到一個新檔案

考量用DATA step下去做的話,首先要排序再利用auto retain累加功能創新變項,最後利用新變項的數值去抓前三筆

proc sort data=test;
     by id ;
run;

使用到IF FIRST.ID的功能,意思是當遇到ID第一筆觀測值時令新變項id2為0

接著往下掃的時候就做累加動作

data test2;
  set test;
    by id;
       if first.id=1 then id2=0;
       id2+1;/*會累加在變項id2裡面*/
       output;/*累加完隨即輸出到資料中*/
run;

因為是要前三筆,所以用where statement抓小於等於3的資料!

data test3;
  set test2;
  where id2<=3;
run;

資料輸出結果如下

data_test3_output

也有人用retain功能,結果亦同!

其實也可以用PROC  SQL方法去做

以後有機會再提



15 Responses to “[問題] SAS 取每個ID前三筆觀測直”

  1.   JUJU Says:

    您好,請問…我有一組資料如下,但我想要整理出在同一個d之下最小的t的資料集,可以請您幫個忙解答嗎?
    ……………………………………………………………………………………………
    id d p t
    1 1 10 80000
    2 1 10 80000
    3 1 10 80000
    4 1 11 80001
    5 1 11 80001
    6 1 12 80002
    7 1 12 80002
    8 1 10 80003
    9 1 10 80003
    10 2 11 80000
    11 2 11 80000
    12 2 11 80000
    13 2 10 80001
    14 2 10 80001
    15 3 12 80002
    16 3 12 80002
    17 3 11 80003
    18 3 11 80003

    =>

    id d p t
    1 1 10 80000
    2 1 10 80000
    3 1 10 80000
    10 2 11 80000
    11 2 11 80000
    12 2 11 80000
    15 3 12 80002
    16 3 12 80002

  2.   Shrimp Li Says:

    hello:
    「同一個d之下最小的t的資料集」

    我看了一下, 可以更具體描述一下縮編的規則嗎?

  3.   JUJU Says:

    您好,

    我先解釋一下我的資料,
    d=date, p=price, t=time;
    我想要找到每一天(d)中最早時間(t)的資料,
    我恰好有找到一個用first.variables的方法可以找到我要的資料集,
    但是另有一個問題,就是,我想要另外加入一個條件,就是每一天中最早時間的第一次出現的價格。

    若我的資料檔案改成如下:
    id d p t
    1 1 09 80000
    2 1 10 80000
    3 1 10 80000
    4 1 10 80001
    5 1 11 80001
    6 1 12 80002
    7 1 12 80002
    8 1 11 80003
    9 1 10 80003
    10 2 11 80000
    11 2 10 80000
    12 2 12 80000
    13 2 10 80001
    14 2 10 80001
    15 3 12 80002
    16 3 12 80002
    17 3 11 80003
    18 3 11 80003
    利用if first.d and first.t and first.p可以變成下面的資料集嗎?
    id d p t
    1 1 09 80000
    10 2 11 80000
    15 3 12 80002
    /*此處的疑問是,因為我是要找到資料集中第一次出現的p,而非排序後第一次出現的p*/
    非常感謝您願意回答.^^

  4.   Shrimp Li Says:

    針對「變項d」去取first感覺上可以得到你要的答案

    你可以寫寫看,貼出來討論

  5.   gafa Says:

    您好:
    我想請問一下..麻煩你囉
    如果我有一筆data..
    id Route
    01 A
    01 B
    02 C
    03 A
    03 B
    03 C

    我要如何下指令讓data整理成:
    id Route1 Route2 Route3
    01 A B
    02 C
    03 A B C

  6.   Shrimp Li Says:

    proc transpose可以做到
    array也可以~
    可以挑一種試試看,再來討論

  7.   gafa Says:

    可以了喔~~謝謝你阿!!^^
    我後來用proc transpose…

  8.   wallace Says:

    可以用Rank Proc

    data test;
    input id $ value;
    x=_N_;
    cards;
    01 123
    01 456
    01 789
    01 112
    01 321
    02 654
    02 987
    02 753
    02 159
    ;
    run;

    proc rank data=test out=temp3(where=(xRank<=3) drop=x );
    by id;
    var x;
    ranks xRank;
    run;

  9.   Shrimp Li Says:

    thank u 😀 又多學了一種procedure

  10.   史丹利 Says:

    想請問如果我想取資料的前三名為1其他為0要怎麼寫呢?? 謝謝!

  11.   Shrimp Li Says:

    根據你的條件排名, 當排名<=3 then 1 else 0即可

  12.   YSL Says:

    您好 我有另一個問題請教
    有2張表
    其一
    tic date ar
    1 20100101 10.6
    1 20100102 10.8
    1 20100103 8.9
    .
    .
    2 20100101 7.6
    2 20100102 3.6
    2 20100103 5.4
    .
    .
    .
    其二
    tic rdq group
    1 20100102 a
    2 20100106 b
    3 20100306 a
    .
    .每個
    要求某rdq(日期)前後30日,按group的累計ar為多少
    也就是兩張表中 以tic相同且rdq=date 為基準日 計算累計30日的ar
    感謝您

  13.   Shrimp Li Says:

    try proc sql
    it’s faster~

  14.   amy Lin Says:

    您好,我想請問一下,我有好幾個id,每一個id都有好幾百筆資料,我要抓取前5筆資料,並且做相乘,應該要怎麼用呢??
    我試過用proc rank選取資料…可是失敗了…
    proc rank data=Ann_date_order out=temp5(where=(xRank<=5) drop=x;
    by ide;
    var x;
    ranks xRank;
    run;

    想請教一下其他的方法要怎麼寫呢…像是proc sql?

    還有要怎麼讓抓出來的五筆資料相乘….

    謝謝喔!!!

  15.   Shrimp Li Says:

    根據你的code:
    proc rank data=Ann_date_order out=temp5(where=(xRank 對id=1來說 1*2*3*4*5=120?


total of 2288494 visits