SAS編程:第五章 通過DATA步讀取SAS數據集

第五章通過DATA步讀取SAS數據集

DATA步是SAS編程中的重要組成部分。本節主要介紹如何使用DATA步來讀取內部數據也就是SAS數據集,並同時創建新的輸出數據集。同時還會介紹DATA步的處理過程,如何對讀取的SAS數據進行加工,如何篩選觀測,選擇變數,如何創建變數,如何改變變數屬性等等。通過這一系列的操作,使我們更加了解DATA步工作的原理。

5.1讀入數據簡介

在SAS中對於可以讀入的數據,按照文件的後綴區分的話,總共分為2大類型,一類是內部文件,另一類是外部文件。

內部文件是文件名以sas7bdat為後綴的文件,這類文件的類型為SAS軟體生成的數據集,是可以直接用SAS軟體打開和讀取的。在程序中,我們主要使用data語句配合set語句進行SAS數據集的讀入,其結構如下圖所示。

外部文件稍微複雜些,也分為2類。一類是無格式的純文本文件,文件後綴包括txt,dat,csv等,這類文件可以用文本編輯器打開,可以直接看到數據本身。在程序中,我們主要使用data語句配合infile語句和input語句進行外部文件的讀取。如下圖所示。這類數據的優點就是結構簡單,壓縮比高,便於存儲體量較大的數據。但是這類數據本身是沒有嚴格格式要求的,所以特殊情況比較多,後面我們會單獨拿出一節來介紹如何讀取外部文件的。第二類是有格式的文件,例如excel,或其他第三方的關係型資料庫文件。在SAS中對於有格式的數據的導入採用proc import 格式。Import過程其語法格式如下:

PROC IMPORT

DATAFILE=「filename」

OUT=SAS-data-set

<DBMS=identifier><REPLACE>;

run;

選項說明:

DATAFILE=

規定要讀入外部文件的地址及名稱,要精確到要具體的名稱,並要寫清文件後綴

OUT=

規定要輸出的SAS數據集,同時可以通過二級引用設置存放的位置

DBMS=

規定外部數據文件格式的引擎 ,如EXCEL、SAV、CSV。

REPLACE

如果存放的位置中有同名文件進行替換,若沒有此選項則不進行替換。

例如:

對於有格式的外部文件的導入,除了import過程,在SAS的中,也可以使用LIBNAME語句,調用SAS/ACCESS介面將一個邏輯庫引用名(libref)與一個外部文件進行關聯。

SAS/ACCESS LIBNAME語句是對我們之前所介紹的LIBNAME語句的擴展,其形式如下。

例如,想要導入一個EXCEL文件,它是有格式的外部文件。可以使用上述語句在DATA步或者SAS程序中直接引用Excel表,相對於把一個Excel表當做一個SAS邏輯庫。例如:

程序執行後,在SAS資源管理器中會出現一個以test_xls命名的邏輯庫,它的引擎類型是EXCEL,而原excel文件中的每一個工作表會被當做一個SAS數據集。數據集的名稱是由工作表名稱和末尾的美元$符號組成,如下圖所示。

外部文件與邏輯庫關聯上以後,就可以像調用其他內部數據集的方式一樣,讀取和複製剛才所創建的excel數據集。需要注意的是,之前我們所提到的命名規則,在默認情況下,特殊字元如$是不允許出現在數據集的名稱當中的。而以SAS/ACCESS LIBNAME語句導入帶格式的外部文件後,EXCEL的表格名稱使得特殊字元包含在數據集名稱中。所以我們要正確調用所建立的數據集時,要使用引號將這種特殊的數據集名稱括起來,後面再緊跟字母n,表示數據集名稱中包含特殊字元。其形式如下圖所示。

5.2讀入SAS數據集

SAS中讀取數據的方式很多,為了方便學習,我們先從最簡單的讀取內部文件SAS數據集的方式開始介紹。這樣可以更好的理解DATA步的運行機制和原理。等掌握好這部分內容後,再推而廣之,繼續學習讀取外部數據的過程和步驟。

首先我們對用DATA步讀取內部數據的步驟進行一個概述。

在上圖中,基本涵蓋了DATA步中大部分的SAS語句,除了與數組和DO循環相關的部分語句。我們看到對於DATA步讀取數據的過程,大致分為4個部分。第1部分主要是定義輸入數據集和輸出數據集的過程。第2部分是通過where或if語句對觀測也就是表格數據中的行進行篩選。第3部分是通過keep/drop語句對變數或屬性也就是對表格數據中的列進行篩選。第4部分是用label語句或者format語句,改變變數的標籤或格式屬性。

接下來的章節會針對每一部分展開進行介紹。

DATA步當中進行數據處理的數據結構是PDV。在DATA步中進行數據讀取的過程是通過PDV來進行的。首先從輸入數據集當中逐行觀測的讀入到PDV當中,經過一系列的變數轉換和處理,再從PDV當中逐行觀測的輸出到指定的輸出數據集當中。PDV是Program Data Vector的簡稱,它是內存中開闢的一個數據存儲區域,在DATA步當中所有對於變數的操作和運算等只在PDV上起作用。

DATA語句表示一個數據步的開始,同時DATA語句後所跟的數據集是被創建的SAS數據集的名字。DATA語句可以創建臨時或永久數據集,這取決於該數據集所存放的邏輯庫的類型,如下圖所示。

SET語句的作用是從SAS數據集中讀入觀測,並在DATA步中等待進行進一步的處理。同樣SET語句能讀入臨時或永久數據集。在默認情況下,SET語句將會從輸入數據集中讀入所有的觀測和變數。如下圖所示。

舉個例子,下面要從一個名為test.sale的永久SAS數據集中創建一個名為work.sale1的臨時SAS數據集。其代碼如下,需要注意的是用SET語句默認是讀取輸入數據集的全部數據和變數,除非DATA步中還有其他的篩選觀測或者變數的條件語句。所以輸出數據集一般是輸入數據集的真子集。

從日誌中可以看出DATA步讀取數據的過程,先從輸入數據集test.sale中讀取12條觀測,然後再向輸出數據集中逐條觀測的輸出,因為DATA步中沒有其他對於觀測或變數的篩選條件語句。所以按照默認規則讀取輸入數據集的全部觀測和變數,輸出數據集當中的數據也是12條觀測和4個變數。

5.3創建SAS變數

通過SET語句讀取完SAS數據集後,接下來我們看要如何創建變數。在DATA步中創建新變數,可以通過賦值語句來處理。在之前的介紹中對於SAS語句的組成,通常都是由關鍵字開頭,以分號結尾。而賦值語句是個特例,它是沒有關鍵字的。賦值語句的作用是可以將一個SAS表達式的值賦給一個變數。其語法形式如下圖所示。

對於賦值語句而言,我們要有三點值得注意。首先是右側的expression表示SAS表達式,表達式是由一系列操作符和操作對象構成,並生成一個目標值。使用表達式可以對變數作變換和賦值,創建新變數,計算新數值以及控制條件語句的運行等。根據操作符的類別不同,表達式總共分為3類:算術表達式,比較表達式,邏輯表達式。賦值語句中第二個需要注意的是語句中間的等號。在SAS中等號既表示賦值作用,也可以表示為比較運算符。其真正的作用要根據等號前後的上下文來確定,如果單獨為一個SAS語句,其作用就是賦值操作符。如果放在WHERE語句後,等號一般表示為比較運算符。賦值語句中第三個需要注意的是,語句左側被賦值的變數。如果事先沒有對變數的類型和長度進行定義,其類型和存儲長度是由賦值語句右側的表達式的值來確定的。在SAS中變數總共有兩種類型,數值型和字元型。在賦值語句中這兩種變數有著非常明顯的不同。對於數值變數,在賦值語句當中它的默認長度為8位元組。而對於字元變數其存儲長度則等於第一次賦值時右側表達式的長度。正因為如此,如果字元變數在賦值前沒有定義長度,而第一次賦值時字元變數的存儲長度不夠。再接下來的過程中則非常容易出現截斷現象。比如下例所示:

代碼執行後,數據集t中變數a的值為「SPS」。我們查看a的屬性,會發現變數a的存儲長度為3,如下圖所示。其原因跟賦值語句的默認操作有關。變數a在賦值前沒有定義變數的長度,而a又是字元型變數。所以其變數的長度為第一次賦值時的長度,也就是表達式『SAS』的長度為3。在第二次賦值時,變數a的長度已經確定為3了,所以將『SPSS』賦給a時,因為變數長度不夠,所以會發生截斷現象。字元型變數默認是左對齊的,因此只會存儲長度為3的前3個字元值『SPS』。

為了避免這種情況的出現,我們可以使用length語句對字元型變數的存儲長度進行定義。這樣就避免了變數長度不足所導致的截斷現象了。Length語句的語法形式如下圖所示。

LENGTH語句是關鍵字,後面緊跟需要被定義存儲長度的變數名,$代表的是該變數的類型是字元型,沒有$默認為數值型。Length則是變數的具體長度。

通過length語句,我們對之前的代碼進行修改,從而就會避免賦值語句默認執行所造成的截斷現象了。修改後的代碼如下圖所示。

之前我們提到在data步處理數據的過程中,主要是通過PDV來進行數據的讀入讀出的。在PDV上我們可以對變數進行創建,計算,篩選等一系列的操作。而在PDV上除了我們所要使用的變數,還有一些SAS自動生成的變數來輔助我們操作。這些自動變數是由數據步語句自動創建的。而這些自動變數雖然在PDV中參與數據處理,但是它們並不會輸出到數據集中。這些自動變數的值在每次data步循環中都會被保留,而不會被初始化為缺失值。我們主要使用的自動變數如下表所示。

自動變數

說明

_N_

DATA步循環的次數

_ERROR_

單條觀察錯誤信息變數

_NUMERIC_

所有數值變數

_CHARCATER_

所有字元變數

_ALL_

所有變數

FIRST.VARIABLE

同一個by變數內第一個觀察

LAST.VARIABLE

同一個by變數內最後一個觀察

_N_表示的是數據集中觀測的個數,不過準確來說它是DATA步循環的次數,而且它是一個累加值,每次DATA步循環的時候_N_的值也會自動+1。而_ERROR_是一個二元變數,它的值只有0和1兩個值,表示當前觀測在讀取時有無錯誤產生。當前觀測在讀取或計算的時候發生了錯誤,該條觀測的_ERROR_的值為1。其他情況_ERROR_的值為0。需要注意的是_ERROR_的值不會累加,它只標識出某條觀測數據的錯誤情況。

_NUMERIC_,_CHARCATER_,_ALL_這三個自動變數是一類。它們分別表示為符合條件的一組變數。_NUMERIC_表示所有的數值變數,_CHARCATER_表示所有的字元變數,_ALL_表示所有變數。它們主要和KEEP或DROP語句進行搭配,來進行指定變數類型的篩選。

FIRST.VARIABLE和LAST.VARIABLE是使用分組語句後所產生的變數,在後面介紹到對數據進行分組操作的時候會再具體介紹的。

5.4SAS函數

接下來,介紹一下SAS函數。不同於其他編程軟體,SAS提供了豐富的內置函數,在數據步執行過程中可以對數據進行各種處理。這些函數能夠幫助節省大量不必要的代碼,從而有效提高代碼的執行效率。

在SASBASE中有幾類常用的函數:字元函數、字元串匹配函數、數學函數、日期和時間函數、統計函數、隨機函數、金融函數、分位數函數等。我們可以通過SASEG模塊中創建新列里的生成「高級表達式」作為輔助工具來查看函數的分類和用法,如下圖所示。

SAS函數就是一個能根據給定參數,進行結算並返回相應結果的程序。在函數中使用由用戶或者系統提供的參數。SAS函數的一般形式,如下圖所示。

Function-name是函數名,其後小括弧內的是該函數所需的參數。函數的參數可以是一個常數,一個變數或是任意的SAS表達式,甚至可以是其他的函數。

下面我們分別列舉一些常用的函數,來熟悉函數的用法。

  1. 描述統計量函數:

SUM函數是最常見的函數,我們在其他軟體比如EXCEL中也會用到。其函數的作用是返回各個參數的和。

SUM函數的一般形式如下圖所示:

需要注意的是,在SUM函數中括弧內的參數必須為數值型數據,而且使用該函數對數據進行加和運算,可以忽略數據中的缺失值。

例如:

  1. 日期函數:

SAS日期函數可以用來提取SAS日期值的信息,或者創建SAS日期值。在SAS中我們常用的日期函數如下表所示。

YEAR(SAS-date)

提取SAS日期的年份信息,返回一個四位數的年份值。

QTR(SAS-date)

提取SAS日期的季度信息,返回一個1到4之間的數。

MONTH(SAS-date)

提取SAS日期的月份信息,返回一個1到12之間的數。

DAY(SAS-date)

提取SAS日期的日信息,返回一個1到31之間的數。

WEEKDAY(SAS-date)

提取SAS日期是星期幾信息,返回一個1到7之間的數,其中1表示星期日,以此類推。

TODAY()

返回當前日期作為SAS日期值

MDY(month,day,year)

根據數值型的月、日、年數據,返回一個SAS日期

其中MDY函數需要注意一下,它可以通過三個參數,以月、日、年的順序,創建一個新的SAS日期值。當所給日期值的格式比較特殊,無法通過指定輸入格式來進行轉換時,可以考慮把日期值當中的年月日信息提取出來,再用MDY函數重新創建一個新的SAS日期變數。例如:

  1. 變數類型轉換函數:

在SAS中,如果將一個字元變數賦值給一個數值變數時,會自動將字元變數的值轉換為數值再賦給數值變數。同樣在算術表達式,比較表達式或者參數需要為數值變數的函數中,都會發生變數類型的隱性轉換。如下圖所示:

但是需要注意的是,字元型變數自動轉換為數值型時會使用W.的輸入格式。而可以進行隱性轉換的數據,必須是標準數值數據,也就是數據中只能包含正負號,小數點和科學計數法符號E。對於非標準數據,如果不做特殊處理,直接進行隱性轉換的話,日誌中會顯示該數值數據無效,並對不符合標準數值格式的字元將以缺失值表示。如下圖所示。

如果想要正確讀取數據,這時我們需要使用INPUT函數強制把字元變數轉換為數值變數。INPUT函數以一個指定的輸入格式對原數據進行讀取並返回相應的值。INPUT函數的一般形式如下:

Source是需要被轉換的變數、常數或表達式,informat是進行轉換所指定的輸入格式。例如:

同樣的,我們也可以把數值型轉換為字元型。當賦值給一個字元型變數,或者用於連接運算符或者用於使用字元型參數的函數。SAS都會自動將數值型數據轉換為字元類型。如下圖所示。

需要注意的是數值型數據自動轉換為字元型數據,默認使用BEST12.輸出方式,同時會將字元型數據進行右對齊。所以對於上面的第二例,字元常量』ROOM』與數值變數Y進行連接。其結果為:

因為數值變數Y的值為10,做字元連接操作時其值自動以BEST12.的格式進行轉換並向右對齊,所以其左側補了10個空格用來填充長度。而為了避免出現這種自動轉換所帶了的前置空格。需要使用PUT函數將數值型數據強制轉化為字元型數據。PUT函數的一般形式如下:

Source為要轉換為字元型的變數,常數或表達式。Format是規定進行轉換的輸出格式。把上面的第二例用PUT函數進行修改,就可以達到我們的要求了。

5.5 SAS中數據的複雜處理

Retain語句:

接下來介紹一個在SAS中十分重要又非常特別的概念:累加變數。之前我們介紹過在SAS中的DATA步里PDV是唯一的數據結構。它是內存中開闢的一個區域,作用是用來進行數據的讀入輸出的。其處理數據的過程是逐條觀測的讀入,經過一系列的變數轉換和處理,再逐一的向輸出數據集中進行輸出。所以在PDV中只能看到當前觀測的數據,如果想要在觀測間進行計算和操作,就必須使用RETAIN語句。

在默認情況下,DATA步中所有變數在每次迭代開始前都會被初始化為缺失值。RETAIN語句可以阻止對新建變數進行重新初始化。RETAIN語句所指定的變數其值會一直保持著,在下次迭代中也可以繼續使用。RETAIN語句的一般形式如下圖所示:

需要注意的是,<initialvalue>是在變數名後面所指定變數初值,用來對變數進行初始化。如果指定數值前有多個變數,則對這些變數都以該初值進行初始化賦值。另外,RETAIN語句對由SET,MERGE或者UPDATE語句所創建的變數不起作用,因為這些從SAS數據集中讀取而來的變數會被自動保留。

在SAS中除了使用RETAIN語句可以定義累加變數以外,一種更好的方式是使用求和語句。求和語句的一般形式如下圖所示。

求和語句的作用如下:

  1. 若加號左邊的變數,之前不存在,則創建該變數。
  2. 自動把該變數定義為REATIN變數。
  3. 在DATA步第一次循環前初始化該變數值為0。
  4. 執行時,將右側表達式的值加在該變數上。
  5. 會自動忽略變數中的缺失值。

在SAS語句中大部分語句都是以關鍵字開頭以分號結束。除了之前介紹的賦值語句外,求和語句也是如此。如果只是做累加操作,使用求和語句效率是最高的。但是因為求和語句默認把變數的初始值設為0,所以如果做累乘或者其他操作,使用求和語句是不能完成任務的,只能使用REATIN語句手動定義變數的初始值。

介紹完RETAIN語句和求和語句後,我們對於數據就可以進行較為複雜的處理了。其中我們經常會使用到的方法,就是對分組數據的累積求和。

在DATA步當中,如果想對某個變數,或某些變數進行分組處理。其前提必須對該數據集和被分組的變數進行排序操作,否則SAS程序在執行時是會報錯的。在SAS中進行數據集中的變數排序,我們使用的是PROC SORT過程步,其語法形式如下圖所示:

「DATA=」後面所跟的是需要進行排序的數據集,「OUT=」後面是輸出數據集用來存放被排好序的數據。如果「OUT=」不寫,默認是用排好序的數據集替換掉「DATA=」後面的數據集。但是我們做數據分析,一般要保持原始數據的完整性,所以建議大家都使用「OUT=」選項,指定一個專門用來存儲排好序的數據集。後面緊跟的BY語句是指以那些變數進行排序。如果BY語句後跟多個變數的話,SAS會以變數出現順序進行依次排序。這裡需要注意的是,默認變數是按照升序排列的。如果想要修改排序的順序,可以使用DESCENDING進行降序排列。而DESCENDING只是針對其後緊挨著的變數起作用。

對數據集排好序後,我們可以在DATA步中使用BY語句,對我們之前排好序的變數進行BY-GROUP過程,也就是可以使SAS分組處理數據。數據步中使用BY語句的一般形式如下圖所示:

這裡需要注意,BY語句在PROC SORT中是用來指定需要進行排序的變數,而在DATA步當中,則是指以哪個變數進行分組處理。同樣的語句在不同的程序步中作用是完全不同的。另外,DATA步中BY語句後面所出現的變數,必須包含在PROC SORT過程中BY語句後的變數中。也就是之前一直所強調的,沒有經過排序的變數是不能進行分組處理的。

使用BY語句對於數據進行了分組,那如何使用分組後的數據呢?數據步中的BY語句為其後所列出的每個變數自動創建2個臨時變數:First.和Last.其語法形式如下圖所示:

對BY分組的第一個觀測,First.變數的值為1,其餘為0。

對BY分組的最後一個觀測,Last.變數的值為1,否則為0。

那如何確定First.與Last.的值呢?如下圖所示:

Last.Class=?

First.Class=1

Class

Age

A

25

A

36

A

12

B

56

B

27

C

18

當前觀測是第一條觀測,First.Class的值為1,Last.Class的值是多少呢?SAS會查看下一條觀測的值。如果兩者相同,說明當前觀測並不是分組的最後一條觀測,Last.的值為0。

如果是第二種情況,如下圖所示:

Last.Class=0

First.Class=0

Class

Age

A

25

A

36

A

12

B

56

B

27

C

18

當前觀測與前一個觀測和後一個觀測的值都相同。說明當前觀測位於組中,First.和Last.的值都為0。

第三種情況,如下圖所示:

Last.Class=1

First.Class=0

Class

Age

A

25

A

36

A

12

B

56

B

27

C

18

當前觀測與下一條觀測的值不同,說明當前觀測位於分組中最後一條觀測了。其Last.為1。

當然除此之外還有一種特殊的情況,也就是該分組中只有一條觀測。這時當前觀測既是分組的第一條觀測也是分組的最後一條觀測。First.和Last.的值都為1。如下圖所示:

Last.Class=1

First.Class=1

Class

Age

A

25

A

36

A

12

B

56

B

27

C

18

接下來介紹條件選擇語句IF-THEN。

IF-THEN語句對滿足特定條件的觀測數據執行THEN後的SAS語句,其一般形式如下圖所示:

其中expression是表達式,它由一系列運算對象和運算符組成,它用來定義選擇觀測數據的條件。Statement是滿足條件後所執行的SAS語句,它可以是任何執行語句,但只能是一條語句。

除此之外,當THEN後的語句沒有執行時,可選ELSE語句給出備選操作。IF-THEN/ELSE語句的一般形式如下圖所示:

當expression的值為真的時候,執行THEN後的語句。值為假的話執行ELSE後的SAS語句。同樣IF-THEN-ELSE語句可以嵌套使用,這樣可以處理expression為多種條件的情況,其形式如同一個二叉樹一樣,如下圖所示:

IF expression

ELSE IF expression

THEN statement

THEN statement

ELSE IF expression

如果因為業務需求,IF-THEN語句中THEN後面不止跟一條語句時。我們可以使用DO…END語句,把需要執行的語句塊放入其中。IF-THEN DO語句的一般形式如下圖所示:

其中DO…END所組成的DO組語句作用很簡單,把他它們看成左括弧和右括弧即可,其一般形式如下圖所示:

Statement1和statement2為IF表達式為真時,THEN語句後跟需要執行的多條語句。這些語句由DO;和END;開始和結束。

分類匯總的實例:

5.6DATA步中進行觀測篩選

在前面的內容中,主要介紹了在DATA步中如何使用DATA語句配合SET語句進行內部數據的讀入和輸出。在默認情況下,SET語句從輸入數據集中讀取所有的觀測和變數。如下圖所示:

日誌窗口中所顯示的系統信息為:輸入數據集kdd99.sale共有12條觀測4個變數,DATA步中除了SET語句沒有其他語句時,會讀取所有這12條觀測,並向輸出數據集work.sale1中進行輸出。

通過添加篩選語句到DATA步當中,可以減少觀測和變數的個數。

首先,先介紹一下在DATA步當中如何對觀測進行篩選。我們使用的是WHERE語句。用WHERE語句可以選擇出滿足特定條件的觀測。其基本的語法形式如下圖所示:

WHERE是關鍵字,where-表達式是由一系列運算符和操作數組成的用來選擇觀測的表達式。其中運算數包含常量和變數,運算符則包含算術運算符、比較運算符和邏輯運算符。

Where-表達式的值只會出現兩種可能,要麼為假(用0值表示),要麼為真(用非0的數值表示)。

表達式中運算數可以是常量也可以是變數。如下圖所示:

對於常量而言,又包含了數值常量,字元常量,日期常量。字元常量中的字元值必須包含在單引號或者雙引號中並且要區分大小寫。數值常量不用引號。對於日期常量一定符合「date9.」d的形式。如下圖所示:

表達式中另一部分運算符則分為3類。

  1. 算術運算符:

算術運算符應該是我們最為熟悉的,它表示要進行運算數之間的算術計算。如下圖所示:

符號

說明

**

*

乘法

/

除法

+

加法

-

減法

例如:

算術運算符要注意優先順序的問題,冪運算>乘除運算>加減運算,當優先順序相同時,從左向右進行運算。

  1. 比較運算符:

比較運算符用來比較一個變數和一個常量,或者一個變數和另一個變數。常用的比較運算符如下圖所示:

符號

運算符

說明

=

EQ

等於

^= ?= ~=

NE

不等於

>

GT

大於

<

LT

小於

>=

GE

大於或等於

<=

LE

小於或等於

IN

在列表中

例如:

需要注意的是,在不同的操作系統中,比較運算符的符號並不一定形同,比如不等於的符號。所以建議大家直接記憶運算符,它是用英語的縮寫進行表示,而且在各個操作系統中都是通用的。另外IN這個運算符需要說明一下,它進行的是一種模糊查詢。查詢變數的值是否在其後的列表當中。列表中的值必須用逗號或者空格分割。所以之前例子中的IN表達式可以改寫成bank=『AB』or bank=『CD』。

  1. 邏輯運算符:

邏輯運算符主要用於合併或者修改表達式。常用的邏輯運算符如下圖所示:

符號

運算符

說明

&

AND

|

OR

^ ? ~

NOT

與運算是所有參加運算的值都為真的時候,表達式的值為真。或運算是所有參加運算的值有一個為真時,表達式的值為真。非運算是取反操作,真為假,假為真。

例如:

除了這些基本的運算符之外,還有一些只能用於where表達式中的特殊運算符,如下圖所示:

符號

運算符

說明

BETWEEN-AND

一個範圍內

IS NULL

缺失值

IS MISSING

缺失值

?

CONTAINS

包含字元串

LIKE

字元串匹配

用BETWEEN-AND運算符可以選擇變數值落入一個值域內的觀測。

例如:

唯一需要注意的是BETWEEN-AND所指定的值域是個閉區間,也就是包含值域的兩個極值。它與下面的這個表達式的作用是完全相同的。

IS NULL和IS MISSING運算符是用來選擇變數值是缺失的觀測。這兩個運算符本身完全等價,沒有任何區別。之前我們介紹過在SAS中變數的類型分為數值型和字元型。對於不同類型的變數,缺失值的表示也是不同的。數值型變數的缺失值是.字元型變數的缺失值為空格。使用IS NULL和IS MISSING這兩個運算符對於變數的類型沒有要求。例如,如下圖所示:

CONTAINS運算符主要用於選擇包含指定的子字元串的觀測。需要注意的是,變數值中的子字元串的位置不重要。當你做比較的時候,運算符要區分大小寫。例如,如下圖所示:

LIKE運算符也是一種用於模糊查詢的運算符。它包含兩個通配符,百分號(%)可以替代任意多個字元。下劃線(_)代表有且僅有一個字元與之匹配。例如,如下圖所示:

WHERE語句除了上述這種形式外,還可以以SAS數據集選項的形式出現,其語法形式如下圖所示:

既在原先WHERE語句的基礎上,把where-expression放在小括弧里並在前面加一個等號。WHERE=數據集選項的作用是根據指定條件,以選擇輸入數據集的一個子集。它可用於輸入和輸出數據集,並只對所指定的數據集有效。

如果WHERE=數據集選項放在輸入數據集的後面,其作用和單獨使用WHERE語句的效果是一樣。都是在數據進入PDV之前先進行篩選。所以WHERE語句後的表達式中的變數必須是輸入數據集中所包含的變數。而如果WHERE=數據集選項放在輸出數據集的後面,其作用則是先在PDV中進行變數的計算,輸出時再進行篩選。這樣對於where表達式中的變數沒有特別的要求。但是因為是先行計算再進行篩選,所以效率會降低不少。這樣就如同if語句一樣,if語句是作用在PDV上,所以也是先計算後篩選的,這些篩選方式的異同如下圖所示:

5.6DATA步進行數據的輸出

在前面的內容中,主要介紹了在DATA步中如何使用DATA語句配合SET語句進行內部數據的讀入和輸出。在默認情況下,SET語句從輸入數據集中讀取所有的觀測和變數。如下圖所示:

如果OUTPUT語句後面沒有選項,則意味著將當前觀測輸出到DATA語句中所命名的所有數據集中。如果指定了相應的數據集,則會向該數據集輸出當前觀測。

在程序中使用了強制輸出OUTPUT語句後會將末尾RUN語句中的隱性輸出覆蓋掉。

OUTPUT語句的在程序中的作用大致分為3類:

  1. 根據OUTPUT出現在程序中的不同位置和OUTPUT出現的次數,可以由一個輸入數據行創建多個觀測。如下圖所示:

  1. 配合DATA語句後建立的多個數據集,OUTPUT語句可以由一個輸入數據文件創建多個SAS數據集。舉例如下圖所示:

  1. 配合多個INPUT語句,OUTPUT可以由幾個輸入數據行合併為一個觀測。

5.7DATA步進行變數篩選

上一部分介紹了如何在DATA步中進行觀測的篩選,也就是對數據表中行數據進行操作。同樣我們也可以對列數據,也就是數據中的屬性或變數進行篩選。默認情況下,SAS將輸入數據集中的所有變數輸出至每個輸出數據集中。在數據步中,用DROP語句和KEEP語句可控制哪些變數會被輸出至輸出數據集中。

DROP語句指定輸出數據集中要刪除的變數的名稱,其語法形式如下圖所示:

KEEP語句指定要寫入輸出數據集的變數的名稱。其語法形式如下圖所示:

Variable-list分別指定輸出數據集中要刪除或保留的變數。

KEEP語句和DROP語句兩者從效率上說沒有本質的區別,至於如何選取,要根據實際的業務需求。比如原數據集中一共有10個變數,如果我們想保留2個變數,顯然使用KEEP語句更加簡潔高效。而如果要保留7個變數,使用DROP語句刪掉3個則更為合適。

同之前所介紹過的WHERE語句一樣,也可以使用數據集DROP和KEEP選項實現同樣的功能。只需要在Variable-list前加上等號即可,其語法如下圖所示:

例如:對於數據集kdd99.kdd99_trans,以下兩個語句等價。如下圖所示:

當KEEP=選項或者DROP=選項用於輸出數據集時,只有指定的變數會被保留或刪除,但所有的變數都可以進行分析處理。這種情況和單獨使用KEEP語句和DROP語句的效果是一樣的。但是如果當使用DROP=選項於輸入數據集時,指定的變數將不會讀入PDV中,因此,不能對其進行分析處理。同樣的,當使用KEEP=選項與輸入數據集時,僅指定的變數會被讀入PDV中,因此,只有這些變數才可用來分析處理。其原理如下圖所示:

5.8 DATA步中改變變數的屬性

之前我們介紹過SAS中的變數一共有5個屬性。其中有3個基本屬性:變數名,變數類型和存儲長度。還有2個可選屬性:標籤和輸出格式。這3個基本屬性是在變數建立之初就創建的,並存儲在數據集的描述部分,是不能修改的。而在本小節的內容,主要是對那2個可選屬性進行設置的。

添加和修改變數的可選屬性主要有2種方式。一種是在DATA步當中修改屬性,這是永久性的修改。這兩個屬性會一直和這個變數綁定在一起。另一種是在PROC步當中修改屬性,這是臨時性修改。這次修改只在這次PROC步過程中有效。而且它的優先順序會高於永久性的修改。如下圖所示:

修改變數的永久屬性,當展示報告時,標籤改變了變數名稱的外觀。輸出格式改變了變數值的外觀。如下圖所示:

用LABEL語句可以將描述標籤賦給變數名。其語法形式如下圖所示:

需要注意的是:

  1. 一個標籤最多有256個字元。
  2. 在單個LABEL語句中可以為任意數量的變數定義標籤。這裡需要注意LABEL關鍵字後面是一條SAS語句,這裡只是為了排版美觀才這麼書寫的。
  3. 在一個DATA步中使用LABEL語句,通過將標籤儲存在這個SAS數據集的描述部分,使標籤和變數永久關聯。

用FORMAT語句可以將輸出格式賦給變數值。其語法形式如下圖所示:

在DATA步中使用FORMAT語句,通過將格式儲存在SAS數據集的描述部分,使格式和變數永久關聯。

例如下圖所示:

數據集中變數date的標籤屬性從「交易日期」永久轉變成了「交易發生日期」。Date的輸出格式從YYMMDD10.永久轉變成了DTAE9.

除了永久性修改變數屬性,我們在PROC步中還可以臨時修改變數的屬性。臨時修改變數屬性只在這次PROC步當中有效,同時臨時改變變數的優先順序要高於變數的永久屬性,等操作完後變數的永久屬性還是不變的。例如,在PROC PRINT過程步中,使用LABEL和FORMAT語句可以臨時修改變數date的屬性。但如果在PROC PRINT列印報表的過程中還要加上LABEL參數才能以變數的標籤做為報表中的列名,否則會以變數名做為列名輸出的。具體情況,如下圖所示:

在進行變數格式的改變時,除了可以使用SAS中內置的格式外,如果SAS中所提供的格式不能滿足需求,用戶還可以通過創建自定義格式,並在其他程序步中進行調用。

用戶創建和使用自定義的格式主要分為2個步驟,首先使用FORMAT過程創建用戶自定義格式。其帶有VALUE語句的FORMAT過程的語法形式,如下圖所示:

VALUE語句後緊跟的是格式名,對於SAS中的格式名還有一些需要注意的地方:

  1. 格式名的命名規則和邏輯庫的命名規則相似,其長度不能超過32個字元。對於字元類型的格式名前加『$』符號。
  2. 為了避免與格式名後的W也就是格式長度進行混淆,格式名中不能以數字結尾
  3. 為了不產生歧義,用戶自定義的格式名不能SAS內置的格式同名
  4. 在FORMAT過程步中是對格式的定義,所以格式名不能以句點結尾

LIB=後指定的是當前分配的邏輯庫,也就是存放自定義格式的位置,默認是存放在WORK邏輯庫下,這樣關閉SAS軟體後,自定義格式會被清除。

值也就是Range(s),它的值可以是單個值,值域或者是唯一值列表。後面值所對應的標籤,長度可達32767個字元,一般會使用引號把值包含起來。

創建完自定義變數後,下一步驟就是在程序步中使用FORMAT語句將自定義的格式應用到指定的變數上。其上兩個步驟,舉例如下圖所示:


推薦閱讀:

英國SAS特種部隊反恐電影《6天》
計量經濟學實證研究中,哪款軟體好?(SPSS,Eviews,Matlab,stata,SAS)
漫談SAS Macro (3) - Macro Quoting, Part II
SAS編程:第六章 通過DATA步讀取外部數據

TAG:數據分析 | SAS | 數據科學 |