手把手教你醫(yī)學(xué)統(tǒng)計(jì)-SAS 編程技巧 - PROC SQL(三)

上一節(jié),我們提到了 CASE 表達(dá)式在 PROC SQL 中的應(yīng)用。事實(shí)上,PROC SQL 支持更為一般的 SQL 表達(dá)式。
1、表達(dá)式的結(jié)構(gòu)
SQL 表達(dá)式由操作數(shù)(operand)和操作符(operator)組成。
操作數(shù)可以是以下任意一種:
常量
變量
CASE 表達(dá)式
任何受支持的 SAS 函數(shù)
任何使用 PROC FCMP 創(chuàng)建的函數(shù)(含數(shù)組參數(shù)的函數(shù)除外)
聚集函數(shù)
查詢(xún)表達(dá)式
操作符可以是以下任意一種:
算數(shù)運(yùn)算符(?+ - * / **?)
比較運(yùn)算符(?lt le eq ge gt ne < <= = >= > ^=?)
邏輯運(yùn)算符(?not and or ^ & |?)
子集運(yùn)算符(?IS IN BETWEEN LIKE CONTAINS EXISTS?)
其他運(yùn)算符(?() ||?)
操作數(shù)可以單獨(dú)使用作為查詢(xún)結(jié)果,但操作符必須與至少一個(gè)操作數(shù)同時(shí)使用才有意義。根據(jù)操作符需要的操作數(shù)的數(shù)量,有一元操作符、二元操作符等。SAS 根據(jù)操作符的運(yùn)算優(yōu)先級(jí)對(duì)表達(dá)式進(jìn)行求值,求值結(jié)果即為查詢(xún)的結(jié)果。可以使用括號(hào)改變表達(dá)式運(yùn)算的順序,這使得我們不必記住所有操作符的運(yùn)算優(yōu)先級(jí),當(dāng)不確定某個(gè)表達(dá)式的運(yùn)算順序時(shí),使用括號(hào)顯式指明運(yùn)算順序即可。
先來(lái)個(gè)例子感受一下:
↑向右滑動(dòng)查看全部代碼↑
這里例子中,生成變量 WEIGHTC 和 HEIGHTC 的表達(dá)式較為簡(jiǎn)單,僅使用了 SAS 函數(shù)和字符串連接符;而生成變量 BMI1 和 BMI2 的表達(dá)式則要復(fù)雜得多。
?? 計(jì)算 BMI1 變量的表達(dá)式中,使用了邏輯運(yùn)算符?=。邏輯表達(dá)式的計(jì)算結(jié)果通常是一個(gè)布爾值,在 SAS 中,若表達(dá)式結(jié)果為 “真”,則運(yùn)算結(jié)果為 1,若為 “假” ,則運(yùn)算結(jié)果為 0。這一特性使得我們可以將邏輯表達(dá)式嵌套在算數(shù)表達(dá)式中,更進(jìn)一步地說(shuō),這其實(shí)可以看成指示函數(shù)(Indicator function)的一種形式。
?? 計(jì)算 BMI2 變量的表達(dá)式中,使用了 CASE 表達(dá)式的運(yùn)算結(jié)果作為算數(shù)運(yùn)算符?/?的兩個(gè)操作數(shù),不難發(fā)現(xiàn) CASE 表達(dá)式的計(jì)算結(jié)果也可以作為操作數(shù)在其他表達(dá)式中使用。
SQL 表達(dá)式大部分用法與 DATA 步是一致的,一些簡(jiǎn)單的用法在此處就不再一一列舉了,下面介紹兩種僅在 PROC SQL 中常用的表達(dá)式用法。
聚集函數(shù)
我們都知道,SAS 在執(zhí)行 DATA 步的時(shí)候是以觀測(cè)為單位的,遍歷每條觀測(cè),并重復(fù)執(zhí)行 DTAT 步中的可執(zhí)行語(yǔ)句。這使得在 DATA 步中對(duì)變量的橫向操作是非常方便的,但與此同時(shí),在 DATA 步中對(duì)觀測(cè)縱向操作卻是較為困難的。
例如:計(jì)算某條數(shù)值變量的均值,DATA 步的做法通常是使用 retain 語(yǔ)句進(jìn)行,通過(guò)保留變量值到下一個(gè)觀測(cè),實(shí)現(xiàn)累加。簡(jiǎn)單的計(jì)算邏輯尚且可以這么做,但如若遇到復(fù)雜的邏輯,我們可能需要聲明多個(gè) retain 變量,并時(shí)刻注意變量值的改變,當(dāng)運(yùn)算完成后,可能還需要將臨時(shí)變量刪除,繁瑣的語(yǔ)句不僅會(huì)降低代碼可讀性,還可能容易出錯(cuò)。
在 PROC SQL 中,有一類(lèi)函數(shù)被稱(chēng)為聚集函數(shù),專(zhuān)門(mén)用來(lái)實(shí)現(xiàn)對(duì)整個(gè)數(shù)據(jù)集中某種信息的匯總。常見(jiàn)的聚集函數(shù)如下:
?N/FREQ/COUNT?: 非缺失頻數(shù)
?NMISS?: 缺失頻數(shù)
?AVG/MEAN?: 算術(shù)平均數(shù)
?MEDIAN?: 中位數(shù)
?MIN?: 最小值
?MAX?: 最大值
?VAR?: 方差
?STD?: 標(biāo)準(zhǔn)差
?STDERR?: 標(biāo)準(zhǔn)誤
?SUM?: 合計(jì)
下面的例子使用了聚集函數(shù)??count()??,??mean()?,? std()??對(duì)數(shù)據(jù)集 class 進(jìn)行了簡(jiǎn)單的統(tǒng)計(jì)量計(jì)算:
↑向右滑動(dòng)查看全部代碼↑
輸出結(jié)果:

如果需要對(duì)不重復(fù)的觀測(cè)進(jìn)行匯總統(tǒng)計(jì),可以在聚集函數(shù)中使用?DISTINCT?關(guān)鍵字,例如,統(tǒng)計(jì)發(fā)生不良事件的受試者數(shù)量:
↑向右滑動(dòng)查看全部代碼↑
子集
在某些時(shí)候,我們可能只需要查詢(xún)結(jié)果中的一個(gè)子集,這時(shí)候可以使用 where 子句進(jìn)行子集的篩選。where 子句支持以下取子集的操作符:
?IS MISSING?: 缺失值
?IN?: 屬于某個(gè)集合
?BETWEEN?: 介于某兩個(gè)值,含邊界值
?LIKE?: 模糊匹配
?CONTAINS?: 變量包含某個(gè)值
?EXISTS?: 子查詢(xún)非空
具體介紹:
IS MISSING
↑向右滑動(dòng)查看全部代碼↑
這個(gè)例子中,使用?IS?操作符篩選發(fā)生日期缺失的所有不良事件的信息。注意:IS 操作符的右側(cè)只能是 NULL 或 MISSING?,二者含義相同。
IN
↑向右滑動(dòng)查看全部代碼↑
輸出結(jié)果:

這個(gè)例子中,使用 IN 操作符篩選名稱(chēng)為 "John" 和 "Thomas" 的學(xué)生信息。
BETWEEN
↑向右滑動(dòng)查看全部代碼↑
輸出結(jié)果:

這個(gè)例子中,使用 BETWEEN 操作符篩選年齡在 11 ~ 12 歲,且姓名首字母在 "L" ~ "T" 的學(xué)生信息。注意:BETWEEN 操作符定義的范圍兩端必須是同一類(lèi)型的值。
LIKE
↑向右滑動(dòng)查看全部代碼↑

這個(gè)例子中,使用?LIKE?操作符進(jìn)行了姓名的模糊匹配,獲取匹配到的的學(xué)生信息。其中:
下劃線 (?_?) : 匹配 0 個(gè)或 1 個(gè)字母
百分號(hào) (?%?) : 匹配 0 個(gè)或 n 個(gè)字母(n > 0)
受限于目前對(duì) PROC SQL 的了解程度,?CONTAINS?和?EXISTS?操作符將在以后進(jìn)行介紹。

相關(guān)文章:
手把手教你醫(yī)學(xué)統(tǒng)計(jì)-SAS 編程技巧 - PROC SQL(一)
手把手教你醫(yī)學(xué)統(tǒng)計(jì)-SAS 編程技巧 - PROC SQL(二)
【文章來(lái)源】水木菁創(chuàng)統(tǒng)計(jì)部