2013-05-29 33 views
1

我有一個SAS中需要轉置的數據集。它的形式是 標識日期類型值 ,我需要將其轉換成 標識日期valueoftype1 valueoftype2 ...有沒有一種有效的方式轉換SAS中的巨大表格

有沒有實現這一點的任何有效的方法?我的數據是huuuge。

例如;

data one; 
input ID date type $ value; 

cards; 
1 2001 A 2 
1 2002 A 4 
1 2001 B 3 
2 2001 B 1 
2 2002 A 5 
2 2002 C 2 
2 2003 C 5 
3 2001 B 6 
4 2002 B 8 
4 2003 B 4 
4 2001 A 2 
; 

我希望將它轉換爲以下形式; (最後三列都瓦拉,值Valb,valC)

1 2001 2 3 . 
1 2002 4 . . 
2 2001 . 1 . 
2 2002 5 . 2 
2 2003 . . 5 
3 2001 . 6 . 
4 2001 2 . . 
4 2002 . 8 . 
4 2003 . 4 . 
+0

你知不知道'PROC transpose'?如果有一種比爲工作而設計的「proc」更有效的方法,我會感到驚訝。 –

+0

我知道'proc轉置',但有沒有其他方法?因爲我的數據集有超過10億個觀測值(幾百萬IDS和幾乎每個ID以及8種不同類型的幾千個日期)。有沒有使用其他功能,如保留等快捷方式?謝謝。 – user2431707

+2

根據我對SAS效率的理解,幾乎所有可以在'proc'中完成的任何事情都應該在'proc'中完成。相反,使用數據步驟通常效率較低。 –

回答

2

PROC TRANSPOSE將做到這一點非常非常有效的,我敢說等於或大於任何其他DBMS在那裏的最有效的方法更好。您的數據也已經按照該方法進行了精美的組織。您只需要按照ID DATE進行排序,除非您已經有該組合的索引(如果您擁有數十億條記錄,則是IMO的必要條件)。沒有其他解決方案會接近,除非您有足夠的內存將其全部存儲在內存中 - 對於這個大小的數據集來說,這是相當瘋狂的(即使是10億條記錄最少也只有7GB,並且如果您擁有數百萬個ID,那麼很明顯不是1個字節ID;我猜25-30 GB或更大)

proc sort data=one; 
by id date; 
run; 
proc transpose data=one out=want; 
by id date; 
id type; 
var value; 
run; 

甲幼稚測試我的系統上,使用以下:

data one; 
do id = 1 to 1e6; 
    do date = '01JAN2010'd to '01JAN2012'd; 
    type = byte(ceil(ranuni(7)*26)+64); 
    value = ceil(ranuni(7)*20); 
    output; 
    end; 
end; 
run; 
proc sort data=one; 
by id date; 
run; 
proc transpose data=one out=want; 
by id date; 
id type; 
var value; 
run; 

該數據集是〜20GB壓縮(。選項壓縮=是)。最初寫入大約需要4分15秒,花了11分鐘進行排序,並花了45分鐘到PROC TRANSPOSE,寫了一個大約100GB的壓縮文件。我猜這是你能做的最好的事情;在這45分鐘內,超過20個可能寫出來(5倍大的數據集將需要超過5倍的寫出時間,加上壓縮開銷);當時我還在做其他事情,所以CPU時間有可能因爲它沒有得到我的整個處理器(這是我的桌面,一個4核心的i5)而被誇大了。我不認爲這是特別不合理的處理時間。

你可能會考慮看看你的需求,也許轉換並不是你真正想要的 - 你真的想要增長你的桌子嗎?機率是你可以實現你的實際目標(你的分析/等),而不需要轉置整個數據集。

+0

作爲一個側面說明;如果你使用的是SPDE,你可以跳過這種排序,並可能從中獲得非常好的表現,遠勝於我在這裏。 – Joe

0
if first.date then a=.;b=.;c=.;d=.; 

不得不被替換爲:

if first.date then do; 
    a=.;b=.;c=.;d=.; 
end; 

if first.date then call missing(a,b,c,d); 

代替

if last.date then do; output; a=.;b=.;c=.;d=.; end; 

而且現在,它應該是足夠了:

if last.date then output; 

我想一個datastep將總是更有效的PROC TRANSPOSE大數據。限制是你必須找出轉置變量的不同值併爲這些變量創建新變量。我認爲這是PROC TRANSPOSE的開銷 - 它首先找出價值。 (對不起,我編輯了你自己的答案,所以現在可能不清楚是什麼問題。)

0

的替代數據的步驟的方法(DOW-loop):

proc sort data = one; 
    by ID date; 
run; 

data two; 
    do _n_ = 1 by 1 until(last.date); 
    set one; 
    by ID DATE; 
    if type = "A" then valA = value; 
    else if type = "B" then valB = value; 
    else if type = "C" then valC = value; 
    end; 
    drop value; 
run; 

在我的系統中,採用的一個喬所使用的大小的數據集1/10,花2分鐘至排序和9分40秒使用proc轉置。 DOW循環在7分4秒內做了同樣的事情。在這種特殊情況下,它並不令人印象深刻,但它與proc轉置相比有一個很大的優勢:您可以使用它來一次轉置多個變量。下面是我使用的代碼:

data one; 
do id = 1 to 1e5; 
    do date = '01JAN2010'd to '01JAN2012'd; 
    type = byte(ceil(ranuni(7)*26)+64); 
    value = ceil(ranuni(7)*20); 
    output; 
    end; 
end; 
run; 

data two; 
    do _n_ = 1 by 1 until(last.DATE); 
    set one; 
    array vals[26] val65-val90; 
    by ID DATE; 
    do i = 1 to 26; 
     if type = byte(64 + i) then vals[i] = value; 
    end; 
    end; 
    drop value i; 
run; 

重命名所有26個換位類型變量動態是有點棘手,但也可以通過電話來完成執行:

data _null_; 
    call execute('proc datasets lib = work nolist;'); 
    call execute('modify two;'); 
    call execute('rename'); 
    do i = 1 to 26; 
    call execute(compress('val' || i + 64) || ' = ' || compress('val' || byte(64+i))); 
    end; 
    call execute(';'); 
    call execute('run;'); 
    call execute('quit;'); 
run; 
相關問題