2012-04-11 141 views
0

我正在嘗試使用兩個循環來計算。但我對循環元素不是很熟悉。使用雙循環的SAS計算

這裏是我的數據:

data try; 
input rs t a b c; 
datalines; 
0 600  
1 600  0.02514 667.53437 0.1638 
2 600  0.2766 724.60233 0.30162 
3 610  0.01592 792.34628 0.21354 
4 615.2869 0.03027 718.30377 0.22097 
5 636.0273 0.01967 705.45965 0.16847 
; 
run; 

我試圖計算的是每個「T」值,用於方程式的A,B和C需要的所有元素。然後我創建了varaibles v1-v6,以便爲每個T1-T6放置方程的結果。在那之後,我創建CS總結v的所有元素

所以我的結果數據集將是這樣的:

rs T   a   b   c  v1  v2  v3  v4 v5  v6 CS 
0 600                      sum of v1 
1 600  0.02514 667.53437 0.1638             sum of v2 
2 600  0.2766 724.60233 0.30162            sum of v3 
3 610  0.01592 792.34628 0.21354            sum of v4 
4 615.2869 0.03027 718.30377 0.22097            sum of v5 
5 636.0273 0.01967 705.45965 0.16847            sum of v6 

我寫了下面的代碼要做到這一點,但得到的錯誤。主要是我不確定如何正確使用i和j來鏈接變量的所有元素。有人能指出我認爲不正確的東西嗎?我知道myabe我不應該使用sum函數來兼容變量的元素,但不確定要使用哪個函數。

data try3; 
set try; 
retain v1-v6; 
retain t a b c; 
array v(*) v1-v6; 
array var(*) t a b c; 
cs=0; 
do i=1 to 6; 
    do j=1 to 6; 
    v[i,j]=(2.89*(a[j]**2*(1-c[j]))/ 
    ((c[j]+exp(1.7*a[j]*(t[i]-b[j])))* 
    ((1+exp(-1.7*a[j]*(t[i]-b[j])))**2)); 
    cs[i]=sum(of v[i,j]-v[i,j]); 
    end; 
end; 
run; 

Forexample,V1將被計算與V同樣[1,1] = 0,因爲沒有用於A B C沒有值。對於v [1,2] =(2.89 * 0.02514 ** 2(1-0.1638))/((0.1638 + exp(1.7 * 0.02514 * 600-667.53437)))*((1 + exp( - 1.7 * 0.02514 *(600-667.5347)))** 2))。 ((1 + exp( - 1))/((0.30162 + exp(1.7 * 0.2766 * 600-724.60233))) 1.7 * 0.2766 *(600-724.60233)))** 2))。

v [1,4]將使用a b c的下一行值,但t將與t [1]相同。直到最後一行。那將是v1。然後我需要對v1的所有元素進行求和,如v1 {1,1] + v1 [1,2] + v1 {1,3] .... v1 [1,6]來使cs [1,1] 。

+0

你的意思是我回答我自己的問題並做綠色標記? – user634455 2012-04-11 16:11:30

+0

我對您的代碼和數據進行了格式化...但是我無法按照您要計算的內容輸出數據沒有意義 – 2012-04-11 16:25:41

+0

輸出數據將包含新變量v1-6和cs。我在輸出數據中想要說的是,每個v都會有方程的值,然後cs將是v變量元素總和的總和。 – user634455 2012-04-11 17:03:43

回答

4

SAS語言不擅長做這些事情,基本上是矩陣計算。儘管您可以使用RETAIN語句進行計算,但DATA步驟通常一次只處理一個觀察值。如果您有權訪問PROC IML(本身執行矩陣計算),則可能會得到比此更清晰的結果,但假定您無法訪問IML,則需要執行以下操作。我不是100%肯定,這是你所需要的,但我認爲這是沿着正確的線路:

data try; 
    infile cards missover; 
    input rs t a b c; 
    datalines; 
    0 600  
    1 600  0.02514 667.53437 0.1638 
    2 600  0.2766 724.60233 0.30162 
    3 610  0.01592 792.34628 0.21354 
    4 615.2869 0.03027 718.30377 0.22097 
    5 636.0273 0.01967 705.45965 0.16847 
    ; 
    run; 

    data try4(rename=(aa=a bb=b cc=c css=cs tt=t vv1=v1 vv2=v2 vv3=v3 vv4=v4 vv5=v5 vv6=v6)); 
    * Construct arrays into which we will read all of the records; 
    array t(6); 
    array a(6); 
    array b(6); 
    array c(6); 
    array v(6,6); 
    array cs(6); 

    * Read all six records; 
    do i=1 to 6; 
     set try(rename=(t=tt a=aa b=bb c=cc)); 
     t[i] = tt; 
     a[i] = aa; 
     b[i] = bb; 
     c[i] = cc; 
    end; 

    * Now do the calculation, which involves values from each 
     row at each iteration; 
    do i=1 to 6; 
     cs[i]=0; 
     do j=1 to 6; 
     v[i,j]=(2.89*(a[j]**2*(1-c[j]))/ 
      ((c[j]+exp(1.7*a[j]*(t[i]-b[j])))* 
      ((1+exp(-1.7*a[j]*(t[i]-b[j])))**2))); 
     cs[i]+v[i,j]; 
     end; 

     * Then output the values for this iteration; 
     tt=t[i]; 
     aa=a[i]; 
     bb=b[i]; 
     cc=c[i]; 
     css=cs[i]; 
     vv1=v[i,1]; 
     vv2=v[i,2]; 
     vv3=v[i,3]; 
     vv4=v[i,4]; 
     vv5=v[i,5]; 
     vv6=v[i,6]; 
     keep tt aa bb cc vv1-vv6 css; 
     output try4; 
    end; 

請注意,我必須構建已知大小的數組,這是你必須知道多少有輸入記錄。

DATA步驟的前半部分構造了讀入輸入數據集中的值的數組。我們讀取所有的記錄,然後我們完成所有的計算,因爲我們在matricies中擁有內存中的所有值。 有一些與RENAMES的擺弄,這樣你就可以保留數組名稱t,a,b,c等,但在輸出數據集中仍然有名爲a,b,c等的變量。

所以希望這可能會幫助你一點。要麼是因爲我誤解了你正在做的事情而迷惑你!

+0

非常感謝湯姆的回答。結果與我在Excel中計算的結果相匹配。我的問題是,當我有更多行數據時,如何在代碼的末尾重命名語句和輸出值? – user634455 2012-04-12 14:50:25

+0

即使我不包括在我的輸出數據的V1-V6值,如果它變得太長時間,我是否需要寫代碼的最後一部分(變量列表)? – user634455 2012-04-12 14:56:34

+0

我可以用它來重命名vv1-vv6 = v1-v6。但是這種相同的對流不適用於輸出vv1-vv6 = v [i,1] -v [i,6];任何人有想法? – user634455 2012-04-12 16:39:31