SAS編程:第六章 通過DATA步讀取外部數據
第六章通過DATA步讀取外部數據
在上一章中主要介紹了如何使用DATA步進行SAS內部數據的導入。在工作或者學習中,我們碰到最多的數據往往不是內部數據,而是以各種形式存在的大量的外部數據。之前介紹過SAS對於數據處理的能力是非常強的,可以這麼說,我們在工作學習中所遇到的大部分數據基本上都可以通過SAS進行讀取,所以學好這章內容,可以使我們充分了解到SAS是如何讀取不同特點的外部數據的。
6.1讀取帶分隔符的原始數據
在SAS中讀取外部文本文件中的數據時,需要給出讀取原始數據所要求的特定信息,比如原始數據的位置、數據集變數和類型,以及SAS如何讀取數據等。SAS會根據這些信息創建數據集。
之前我們介紹過SAS中可以讀取的外部原始數據分為2種,一種是帶格式的外部數據,我們使用PROC IMPORT過程步或者使用LIBNAME語句調用SAS中的ACCESS模塊進行數據的讀入。而對於無格式的外部數據SAS使用INFILE語句配合INPUT語句進行數據的讀取。
在DATA步中進行原始數據的讀取大致的框架如下圖所示:
在這個框架中的大部分SAS語句我們都在之前的章節中介紹過了,只有INFILE和INPUT語句沒有介紹過。SAS讀取數據的框架大體是相同的。我們先從最簡單的讀取內部數據入手,然後再學習一些新的SAS語句,就可以很快掌握在SAS中讀取原始數據的過程了。
INFILE語句指定原始數據的位置和名稱。原始數據文件的位置,也就是該原始數據文件在磁碟中的絕對路徑。其語法形式如下圖所示:
INPUT語句描述了原始數據文件中的SAS是如何讀取數據的。其語法形式如下圖所示:
在讀取原始數據文件並創建SAS數據集之前,必須先檢查原始文件,確定要要讀取的數量值在原始數據中的格式,並基於這些信息選擇,並基於這些信息選擇讀取數據時使用的方法。先數據文件,確定要讀取的在SAS中使用INPUT進行原始數據的讀取。SAS軟體一共提供了3種基本輸入方式:
- 列表輸入
- 列輸入
- 格式化輸入
這3種輸入方式可以單獨使用,也可以組合使用,還可以和SAS提供的各種修飾符以及指針控制結合使用,如輸入格式、行列控制符,行列指針控制等……
- 列表輸入
列表輸入(List Input)用於讀取原始數據記錄中每個欄位有至少一個分隔符隔開,並且數據值中不包含該分隔符的原始數據。列表輸入默認分隔符為空格,連續的分隔符會當成一個分隔符處理。例如sales.csv這個原始數據,其格式如下圖所示:
選取正確的輸入方式,主要取決於原始數據的數據特點。如果原始數據中每一個數據,所有欄位都是用分隔符進行分割的。我們可以採用列表輸入的方式進行數據讀取。其原始數據的特點如下圖所示:
我們看到在上例的原始數據中,每一個數據都是用逗號進行分割的。其特點滿足按列表輸入的要求。
在SAS中默認是以空格作為分隔符的。如果要改變默認的分隔符,需要在INFILE語句中使用DLM=選項指定空格以外的分隔符。其語法形式如下圖所示:
DLM=後面用單引號或者雙引號指定好原始數據中所使用的分隔符。
使用列表輸入的方式時,對於原始數據中的標準數值格式和非標準數值格式是區別來輸入的。標準數值格式是指SAS中不用任何特殊選項可以讀入的數據,如下圖所示:
而非標準數值數據是指SAS沒有特殊選項就不能讀入的數據,如下圖所示:
在SAS中標準數值數據是只能包含正負號,小數點,科學計數法的數據。其他數據都為非標準數值數據。
對於標準數值數據的列表輸入,其基本的語法形式如下圖所示:
需要注意的是,變數一定要按照它們在原始數據文件中出現的順序從左到右依次排列。變數默認的類型是數值型,尖括弧中的$符號代表將變數定義為字元型。字元型和數值型變數的默認長度都是8個位元組。當輸入長度超過8個位元組時,讀入字元型變數將會出現截斷現象。要解決這個問題,我們可以使用LENGTH語句顯性定義變數的長度。對於剛才所列出的sales.csv的原始數據,通過剛才的定義,我們知道前7個變數的值都為標準數值數據,其中第6個變數的長度超過默認的8位元組,所以我們要使用LENGTH語句配合INPUT語句進行數據的讀取,代碼如下圖所示:
我們可以列印一下新生產的數據集的報表,查看一下數據是否讀取正常。其結果如下圖所示:
我們看到前7個變數讀取都沒任何問題,在用LENGTH語句定義好變數長度後,字元型變數也沒有截斷現象產生。
接下來要讀取原數據中最後兩個非標準數值數據的變數。
對於非標準數值型數據,SAS是無法自動識別原始數據中的數據格式的。如果強行讀取,在日誌中會顯示出該變數類型不匹配,同時該變數的值會被設定為缺失值。為了能正確讀取這類數據,可以使用一些特殊選項來指定變數的格式。如下圖所示:
需要注意以下幾點:
- 高亮部分語句的含義是,用:修飾符可以指定某個變數一個具體的輸入格式,從而用來讀入帶分隔符的非標準數值數據。
- 輸入格式是SAS中變數格式的一種。它是SAS將數據值讀入變數的一個說明。
- 對於列表輸入來說,輸入格式的寬度可以不指定或者省略。
- 對於字元變數來說,如果先前未定義長度,輸入格式的寬度決定了變數長度。
SAS輸入格式同之前介紹的輸出格式的形式非常類似,如下圖所示:
$表明該輸入格式是字元格式,如沒有$預設默認為數值格式。
Informat是輸入格式的格式名稱,它分為SAS中內置的或者用戶自定義的格式名稱。
W指定在輸入數據中所讀入的列數。
D是指數值格式中的一個可選的小數點的位數。
.這個分隔符十分重要,它用來表示這種形式是否為SAS格式。
接下來舉例介紹一下SAS輸入格式的作用。
在列表輸入中,輸入格式被用於將非標準數值數據轉化為SAS數值。如下圖所示:
輸入格式
原始數據值
SAS數據值
COMMA.
DOLLAR.
$12,345
12345
COMMAX.
DOLLARX.
$12.345
12345
EUROX.
€12.345
12345
MMDDYY.
010160
01/01/60
01/01/1960
0
DDMMYY.
311260
31/12/60
31/12/1960
365
DATE.
31DEC59
31DEC1959
-1
需要注意的是在列表輸入中,輸入格式的W也就是寬度,可以省略。
對於上例中最後兩個非標準數值數據的變數,程序中高亮部分,通過增加:+輸入格式的方式進行數據的讀入,如下圖所示:
這樣就完成了對於帶分隔符的原始數據,用列表輸入的方式進行讀取。
6.2讀取其他形式的原始數據
除去列表輸入以外,讀取原始數據的方式,還有按列輸入和格式化輸入。如果原始數據記錄中的欄位並不是按照分隔符隔開的,而是每條記錄中的的數據值佔據相同的列時,可以考慮使用按列輸入的方式。按列輸入可以讀取標準數值數據,如果要同時讀取標準數值數據和非標準數值數據,可以考慮採用更為複雜的格式化輸入。可以使用格式化輸入的原始數據,如下圖所示:
其數據值的布局有一定規律,比如位於第1至第4列的數據值代表的是Customer Type其具體的情況如下圖所示:
格式化輸入是指在INPUT語句中提供特殊的指令,以便SAS可以正確地讀取原始數據記錄中的數據值。這些特殊指令就是之前所介紹過的輸入格式。格式化輸入是把按列輸入的方式和讀取非標準數值數據結合在一起,從而確保數據值可正確的從原始數據記錄中讀入。
格式化輸入方式讀取數據的一般語法形式如下圖所示:
INPUT語句後的指針控制用於移動輸入指針到讀取數據的起始位置。然後對變數進行命名,最後規定該變數的輸入格式。舉例如下圖所示:
其中列指針控制分為兩種:
@n是絕對引用,其作用是將指針移動至第n列
+n是相對引用,其作用是將指針向後移動n列
而輸入格式跟之前的列表輸入不同,需要定義兩方面內容,一個是輸入區域的寬度,另一個是怎樣讀取區域內的數據值。
對於之前所舉的例子在offers.dat中要讀取高亮部分的第一個變數,使用的程序如下圖所示:
@1表示從第1列開始進行讀取,Cust_type為變數名,4.則是讀取原始數據所用的輸入格式。
之前用列表輸入和格式化輸入讀取原始數據,所使用的數據都是比較規整的。但是在工作和學習中,會根據數據文件的格式,需要使用更加高級的特徵來正確有效地讀取原始數據。
在一個DATA步中可有多個INPUT語句。在默認情況下,當執行到INPUT語句時,程序會自動將下一條觀測數據放入輸入緩衝區。這樣可以從多條記錄中創建一個觀測。有時一條觀測的數據會分布在原始數據的多行中,而我們只關心部分數據行的信息,這時可以使用單獨的空INPUT語句或/行指針控制符來跳過不關心的行。例如原始數據如下圖所示:
方法一,我們可以通過多條INPUT語句進行讀取,對於原始數據中不需要的第三行,可以直接用INPUT空語句進行讀取。其程序如下圖所示:
方法二,除了使用多條INPUT語句之外,我們還可以使用/行控制符,強制讀入下一行數據到輸入緩衝區,並賦值給變數。其代碼如下圖所示:
當SAS遇到一個「/」時,原始數據中的下一行記錄將被讀入。所以行指針控制符「/」和INPUT語句是等價的。
想改變INPUT語句的這種默認的讀取模式,可以使用行保持符進行控制。
如果在INPUT語句的結束處指定單個@的行保持符(Line-hold Specifier),輸入緩衝區的數據則會保持住,當前迭代中的下一條INPUT語句可以繼續使用。SAS會記錄下列控制指針在輸入緩衝區的位置。但是,當程序返回DATA步開始下一次循環時,輸入緩衝區中的數據會被釋放。
在INPUT語句的結束處使用由兩個@的行保持符(形式為@@)時,輸入緩衝區中的數據會保持住,直到讀到原始數據的文件尾(EOF)為止。這樣,程序在執行INPUT語句時就不會自動將下一條數據記錄讀入到輸入緩衝區中,同時,程序返回DATA步的開始處繼續執行時,輸入緩衝區的數據也不會釋放。但是SAS會保留指針在當前記錄中的位置,這樣,程序就能讀取記錄中的每個值了。
單尾@,雙尾@舉例……P58
當DATA步從外部文件中讀取原始數據時,如果SAS在為所有變數讀到數據之前就遇到了輸入行的末尾,可能會有問題,尤其是當INPUT語句要求讀入的變數長度超過輸入緩衝區中的數據,或記錄中包含缺失值又沒有佔位符時。默認情況下,SAS讀入一行記錄,當INPUT語句在當前輸入行找不到所有的數據值時,會自動讀入下一行數據記錄,DATA步中的語句繼續執行,但可能產生意外結果(即未按照預期讀入數據)。這時,可以在INFILE語句中指定MISSOVER選項,從而改變SAS的默認行為。
如果缺失數據是由兩個連續分隔符表示,默認情況下,SAS會把相鄰的兩個分隔符當成一個分隔符來處理。這樣當數據中的缺失值出現在中間位置時,在默認的情況下,讀入數據也會發生偏差,產生錯誤。為了解決這種缺失值出現在數據中間的情況,我們可以使用DSD選項,改變SAS的默認行為。
推薦閱讀:
※關於定性變數(可能為等級資料)的分析,該選用卡方檢驗還是秩和檢驗,如何進行選擇?
※ORDER=DATA in PROC REPORT
※sas初級1
※【SAS正則表達式】提取文本數據,分析師小王初上手!| 1. PRXMATCH ()