2011-04-29 93 views
2

我正在尋找一種方法來創建包含數據集的某些值的字符串變量,同時通過數據步驟。SAS變量級聯通過數據步驟

實施例的數據集work.test:

AddToStringYN Value 
    Y   One 
    Y   Two 
    N   Three 
    Y   Four 
    N   Five 

所以在結束時,變量將如下所示:OneTwoFour(或甚至更好FourTwoOne)。 這看起來很簡單,但我似乎無法找到辦法。 我也試圖與宏觀變量工作是這樣的:

%let stringvar=; 
Data _null_; 
    set work.test; 
    if AddToStringYN = "Y" then do; 
    call symput('stringvar',"&stringvar" || strip(value)); 
    end; 
Run; 

但是這給:

GLOBAL STRINGVAR Four 

所以我只得到了最後一個值。我明白這一定是因爲我對這個宏觀設施的誤解,但我不明白爲什麼只有變量的最後一個值。 我以爲只是最後一次symput被稱爲是實際執行或東西,但後來當我的代碼調整爲:

%let stringvar=; 
Data _null_; 
    set work.test; 
    if AddToStringYN = "Y" then do; 
    call symput('stringvar'||strip(value),"&stringvar" || strip(value)); 
    end; 
Run; 

那我讓他們都:

GLOBAL STRINGVARONE One 
GLOBAL STRINGVARTWO Two 
GLOBAL STRINGVARFOUR Four 

所以我最後的猜測是,通過數據步驟,'調用symput ...'行實際上被添加到宏處理器,其中「& stringvar」已被替換,並且僅在最終語句被全部執行之後。
這是一個很好的假設還是存在另一種解釋? 回到原來的問題:是否有一個簡單的方法來實現這一點(具有所需的變量)?

回答

2

問候 似乎很簡單,這裏是我的解決方案:

data a; 
set test end=eof; 
length cat $100.; 
retain cat; 
if AddToStringYN = "Y" then do; 
    cat=trim(left(cat))||trim(left(value)); 
end; 
if eof then do; 
    call symput("VAR",cat); 
    output; 
end; 
run; 

%put VAR=&VAR; 

在這個例子中,你必須在列「CAT」的數據集的變量的級聯和你有一個macrovariable VAR與同樣的名單

+0

完善!我記得嘗試使用這樣的結構(保留和可變重用的組合),但它不起作用。現在還找不到什麼不同,但它工作!確實很簡單......如果你知道在哪裏看;) 謝謝! (關於附加問題的任何想法,如果我的邏輯是正確的宏變量?) – Yoh 2011-04-29 11:07:10

+1

另外,嘗試用cat(),catt(),cats(),catx()函數替換trim(left() 。它們非常靈活,更易於使用,併爲您自動進行類型轉換!可用SAS9以上... – 2011-04-29 19:40:29

+0

@Rob將調查,使用剝離()現在... – Yoh 2011-05-02 12:43:48

5

以下是我對your identical question on RunSubmit.com的回答。我認爲你和@Fabio可能會過度設計解決方案,它不需要任何迭代數據步驟代碼...

首先,簡單的方法來做你想做的事就像這樣:

proc sql; 
    select Value into :StringVar separated by '' 
    from work.test 
    where AddToStringYN='Y' 
    ; 
quit; 

在這裏,你可以採取與SAS/MACRO的SQL接口的優勢,使用select into語法。您甚至可以添加order by子句以獲得您要查找的特定訂單。第二,既然你已經發現了SAS宏的工作方式,並且你很想理解它:在你的第一個例子中,編譯器在執行你的代碼之前做的第一件事就是解析&stringvar的值,在那一點上是空的。所以在編譯之後,用這個標記代替,你的代碼看起來像這樣對SAS ...

%let stringvar=; 
Data _null_; 
    set work.test; 
    if AddToStringYN = "Y" then do; 
    call symput('stringvar',"" || strip(value)); 
    end; 
Run; 

...那麼SAS繼續並運行該代碼(這恰好是有效的代碼,但是將空字符串連接到某個東西的開頭)。並且由於數據步驟的工作方式,數據步驟的每次迭代實際上將取代StringVar的值,這就是爲什麼在數據步驟結束時,剩下的是讀入的最後一個值。

+0

看到你的答案RunSubmit,沒有時間回覆yet.First非常感謝,尤其是關於SAS宏。事實上,我一直在考慮它的工作方式,解決宏觀變量只發生一次,而不是數據步驟的每一次迭代。 關於proc sql的使用:我總是學習使用SAS代碼優先於SQL(即處理時間)。我不知道這個例子是否支持這個例子。 – Yoh 2011-05-02 13:22:24

+1

@Yohsoog:SAS數據步驟代碼與PROC SQL的性能沒有嚴格的規則 - 哪一個更快取決於各種因素。您可以隨時試用這兩種解決方案,並查看日誌,以查看這種情況下最快的數據。但也有其他一些考慮因素,例如代碼可讀性,可維護性,對其他人的清晰度,編碼標準等。至於我,我會傾向於使用PROC SQL方法,除非您還在其中做了很多其他的東西數據步驟,使得I/O值得獲得結果。 – sasfrog 2011-05-02 22:07:19

+0

是的,在這種情況下,我在數據步驟中做了很多其他的事情。數據步驟實際上循環遍歷一個生成完整xml的表。而且我在這裏放置的字符串在同一個數據步驟中的其他地方也會被分開,所以使用PROC SQL方法甚至是不可能的。但是,爲了可讀性等考慮,這是一件好事。 – Yoh 2011-05-03 07:48:04