用SAS如何读取数据
你可能有各種形式的數據,包括手寫在紙上、存放在電腦上、或是在數據庫管理系統里,不論如何,總有一種方法可以讓SAS來讀取。
SAS讀取的數據的方法主要有以下幾種類型:
? 直接輸入;
? 從原始數據文件中創建一個SAS數據集(creating SAS data sets from raw data files);
? 將其他軟件中的數據文件轉換成SAS數據集;
? 直接讀取其他軟件的數據集;
直接輸入
?View table窗口可以讓你以表格形式輸入數據,可以定義變量、設置屬性,如name、length和 type(character or numeric).
? SAS 企業向導模塊
? SAS/FSP 模塊,是Full Screen Product的簡稱,可以設計定制的數據輸入窗口,也有檢測數據輸入錯誤的功能(The SAS/FSP product is licensed separately from Base SAS software.)。
從原始數據文件中創建一個SAS數據集
你有兩種方法讀取原始數據文件:
? 數據步可以讀取任何形式的原始數據文件,比如text, ASCII, sequential, flat files。
? 導入向導(Import Wizard)、導入過程(IMPORT procedure)適用于UNIX、OpenVMS和 Windows操作環境的簡單方法,可以讀取CSV(comma-separated values)和其他一些限定的文件類型。
將其他軟件中的數據文件轉換成SAS數據集
如果數據在一個軟件中以某種格式存放,但需要用另一種軟件分析時,就會很麻煩。有幾種方法可以將某種軟件中的數據轉換成SAS數據集:
? 如果安裝SAS/ACCESS模塊,可以用導入過程(import procedure)和導入向導(Import Wizard)將Excel、Lotus、dBase和Access文件導入SAS數據集。
? 如果沒有安裝,可以用存放數據的軟件創建一個原始文件,并用數據步或導入過程(import procedure)讀取。很多軟件都可以創建CSV文件。
? Windows操作環境下也可以用動態數據交換技術(Dynamic Data Exchange,DDE)。前提是必須有一個其他的Windows程序與SAS同時運行,再使用DDE和數據步。
直接讀取其他軟件的數據集
? SAS/ACCESS產品可以不用轉換數據格式讀取數據,并適用于大部分數據庫管理系統,包括ORACLE,DB2,INGRES和 SYBASE(但使用方法本書沒有介紹)。
? 使用Excel engine和Access engine來讀取這兩種類型的數據。(SAS幫助文檔)
? 還有其他的一些數據引擎(data engines)來讀取數據,如SPSS engine(附錄D),查
使用DATA步,通過INFILE語句指定原始數據文件;
SAS提供了以下3種基本輸入方式:
列表輸入
按列輸入
格式化輸入
一、列表輸入
1) FILENAME語句指定到單個文件的文件引用
2) FILENAME語句指定到一組外部文件存儲位置的文件引用
列表輸入(List Input)用于讀取原始數據記錄中每個字段由至少一個分隔符隔開,并且數據值中不包含該分隔符的原始數據。列表輸入默認分隔符為空格,連續的分隔符會當成一個分隔符處理,INPUT語句中包含了簡單的變量名稱列表。
在SAS窗口中提交如下代碼:
INPUT語句會逐行順序地讀取inventory.dat中的數據值,并賦值給變量。在讀取每行數據時,遇到空格就停止讀入當前數據值,并從非空格處讀入下一個數據值。
3) 使用INFILE語句的選項DLM=指定分隔符
當原始數據中數據記錄的數據值未使用空格,而是使用其他分隔符時,需在INFILE語句中使用DLM=選項,告訴SAS讀入數據時需要使用的分隔符。
下面將上面外部數據文件的內容稍作修改以便比較。文件inventory_dlm.dat的內容如下,數據記錄中的各數據值之間由逗號(,)隔開。
正確讀取該數據文件的代碼如下:
使用DLM=選項可處理原始數據記錄中數據值中包含空格的情況。此外,使用DLM=選項的DATA步也可以很好地處理數據中的缺失值。如果接連有多個指定的分隔符,也會當成一個分隔符處理。但如果分隔符之間有空格,則該空格會當作缺失值讀入變量并寫入數據集。例如,當數據文件inventory_missing.dat的內容如下:
注意:當用dlm=“,”時,想要識別缺失數據必須使用空格作為占位符,否則沒有空格只有兩個逗號時,數據只會讀入該行的第一個數據,并且之后的數據也不會讀入;
提交與上例相同的SAS代碼,PRINT過程打印的數據集內容如下圖所示,其中第3個觀測Instock變量為默認值:
4) 使用INFILE語句的選項DSD
DSD (Delimiter-Sensitive Data)
指定選項DSD后,如果數據值是由引號引起來的,可以將數據值中的分隔符當成是數據值的一部分讀入,字符值中的引號在讀入PDV時會被刪除。DSD選項將默認的分隔符設置為逗號,還改變了使用列表輸入時SAS處理分隔符的方式,比如,如果有兩個連續的逗號,將被當作缺失值。
選項DSD還可以和其他選項(例如DLM=和DLMSTR=)一起使用。
5) 使用INFILE語句的選項missover
MISSOVER:會在DATA步的本次迭代中阻止INPUT語句讀入原始數據的下一條記錄,并將PDV中所有未賦值的變量保持為缺失值(PDV中變量未賦值時就為缺失值)。當原始數據記錄中的最后一個或多個字段沒有值且沒有占位符時,并且希望SAS將對應的變量置為缺失值時使用MISSOVER。
外部數據文件missover.dat的內容如下,依次包括課程編號、課程名稱、參加課程人數和講師姓名等信息。其中第二條記錄中未提供參加課程人數和講師姓名,也沒有占位符。
在INFILE語句中加上MISSOVER選項,代碼如下:
PRINT過程打印的數據集如下圖所示:
5) 使用INFILE語句的選項turnover
默認情況下(選項為FLOWOVER),當原始數據記錄長度小于INPUT語句的預期時,INPUT語句自動讀入下一條數據記錄。當指定選項TRUNCOVER時,即使當前輸入行數據的長度小于INPUT語句的預期,也會將當前輸入行的數據賦值給當前處理的變量,并將其他沒有賦值的變量設置為缺失值。
TRUNCOVER選項常用于處理變長的原始數據記錄,可在INPUT語句中定義足夠長度的變量,即使當前數據記錄中的數據長度小于變量指定的長度,也可以將該記錄從緩沖區讀入PDV,并寫入數據集,以便進一步處理。
原始數據文件comments.dat的內容如下,共3條記錄,全部為文本,文本長度不確定。
使用TRUNCOVER選項讀入該文件記錄。設置變量Text的輸入格式為“$500.”,當原始記錄中文本長度不足500個字符時,TRUNCOVER選項會將當前輸入緩沖區中的所有內容寫入PDV,并寫入數據集。
PRINT語句打印的數據集內容如下圖所示。可以看到,所有的評論信息都讀入了數據集中。
MISSOVER與TRUNCOVER的不同之處在于,如果當前變量沒有讀到要求長度的數據,MISSOVER會將當前變量的值也置為缺失值。還是以上面的示例為例,如果將TRUNCOVER換成MISSOVER,所生成的數據集中3個觀測值都為缺失值。
5) 使用INFILE語句的選項PAD
選項LRECL為系統選項指定用于讀寫外部文件的默認邏輯記錄長度。LRECL指定邏輯記錄的長度為1(字節)或1024(k字節)的倍數。例如32表示32字節、16k表示16384字節。該選項的范圍為1~32767。在SAS 9.4中,LRECL系統選項默認值為32767,通常不需要修改。
PAD和NOPAD選項控制SAS是否使用空格對從外部文件讀入的記錄進行填充,使其達到選項LRECL=指定的長度。默認設置為NOPAD。
當使用PAD選項時,SAS會自動用空格填充從外部文件中讀入的記錄長度。
還是以上面的comments.dat文件為例:
下面在INFILE語句中使用PAD選項,代碼如下:
PRINT過程打印的數據集內容如下圖所示。DATA步正確讀入了文件中的所有評論。
6) 使用INFILE語句的選項控制輸入
FIRSTOBS=
FIRSTOBS= 選項告訴SAS從哪一行開始讀取數據,當數據開頭有些說明信息,或者想要跳過某些行時,這個選項很有用。例如,如下原始數據文件中,開頭兩行是關于數據的描述:
那么用如下程序可以讓SAS從第三行開始讀取數據:
OBS= OBS=告訴SAS一直讀取到哪一行位置,注意是行而不是觀測值(有的觀測值占據多行)比如,如下的原始數據文件中,結尾處還有一句不需要的數據說明時。就需要這個選項:
用FIRSTOBS=3和OBS=5就可以讀取第三行到第五行的數據:
二、按列輸入
當原始數據記錄中的數據值在每條記錄中占據相同的列時,可使用按列輸入的方式。按列輸入(Column Input)可以讀取固定列的數據。
文件customer.dat的內容如下,其中,第114列為產品編號,第1626列為附屬品牌,第2829列為專賣店數,第3135列為產品庫存
數。
三、格式化輸入
上面介紹的按列輸入與列表輸入一樣,只能讀取標準的字符或數字值到數據集中。SAS還可以讀取特殊格式的數字數據,例如二進制數據、日期/時間(01FEB2013),或者包含逗號(1,262)、貨幣符號($87.3)等特殊字符的數字值。在這種情況下,就需要使用格式化輸入(formatted input)了,即在INPUT語句中提供特殊的指令,以便SAS正確地讀取原始數據記錄中的數據值。這些特殊指令稱為輸入格式(Informat)。格式化輸入組合了按列輸入特征和讀取非標準化數字或字符值的能力,保證數據值可正確地從原始數據記錄中讀入。
來看個示例,原始數據文件sales.dat的內容如下,該文件中原始數據記錄包含字段依次為員工ID、部門、銷售額和上次修改日期,其中銷售額和日期都不是標準數字值,需使用對應的輸入格式。
讀入處理該文件的SAS代碼如下,其中Sales和Date變量分別使用了輸入格式comma6.和date9.,Emp_ID和Dept使用的是上面介紹過的按列輸入方式。
在INPUT語句中,還使用了相對列控制符號+1和絕對列控制符號@22,分別表示將當前的輸入列控制指針向前移1位和將該指針直接移動到列22。在上面的示例中,程序讀入一行記錄到輸入緩沖區后,列控制指針的移動情況如下:
·第1~5列寫入Emp_ID,列控制指針在第6列。
·第7~9列寫入Dept,這時列控制指針在第10列。
·+1將列控制指針移到第11列。
·開始讀入comma6.中指定的6列,即將第11~16列使用輸入格式轉換后寫入Sales,這時列控制指針在第17列。
·@22將控制指針直接移到第22列,讀入date9.中指定的9列,即第22~30列,然后使用該輸入格式進行轉換,并寫入Date。
四、帶修飾的列表輸入
將列表輸入、輸入格式和修飾符結合起來,結合后就成了帶修飾的列表輸入(modified list input),這樣可以使用列表輸入方式更靈活地讀入數據。
·&修飾符(ampersand format modifier):使用列表輸入時,該修改符能夠讀入數據值中包含一個或多個嵌入空格的字符值,并指定字符的輸入格式。SAS讀入數據直到遇到兩個連續的空格或達到所定義的數據長度或輸入行結束才停止。&修飾符解決了使用列表輸入方式讀取數據值中包含嵌入空格的問題,但要求該包含空格的數據值與下一個數據值之間至少間隔兩個空格。
·:修飾符(colon format modifier):使用列表輸入時,該修改符可以在變量名后指定輸入格式。SAS讀入數據直到遇到空列、達到所定義的數據長度(對字符型變量來說)或輸入行結束才停止。:修飾符可以讀取超過8個字節的字符數據和包含特殊字符的數字字符。
·~修飾符(tilde forat modifier):可以讀入并保持數據值中的單引號、雙引號和分隔符。
原始數據文件customer2.dat的內容如下,每條記錄包含聯系人信息:客戶ID、名字和出生日期,其中名字里面嵌入了空格,可使用&修飾符讀入。注意,使用&修飾符要求名字和出生日期之間為兩個空格。
處理該數據的SAS代碼如下,其中,Name變量使用了&修飾符讀入帶空格的名字,并指定輸入格式為$20.,所以Name變量的字符長度為20個字節,而且SAS會將緩沖區中的20個字符讀入Name。Birth_Date使用了:修飾符讀入日期格式的數據。
@’character’ 列指示器
@column列指示器可以讓SAS直接從某列開始讀取數據。但有時候你不知道要讀取的數據是從哪列開始,此時你只要知道要讀取的數據的前面那個字符或單詞即可。比如有一個關于狗的原始文件,你想要讀取狗的品種號,但文件排列很凌亂,只知道品種號跟隨在單詞breed后面,那么可以用如下方式讀取:
Input @’Breed:’ DogBreed $;
例子 web日志是凌亂數據的一個很好例子,下面是一個網站的web日志,數據開始于訪問IP,后面有訪問日期、訪問文件名等信息。
現在想要讀取訪問日期和訪問的文件名,但是它們每行中所占據的列的位置都不同,而且文件名的長度每行都不一樣,那么SAS讀取這種文件通過如下方式:
@’[’作為列指示器,告訴SAS讀取[之后的內容,@’GET’告訴SAS讀取GET之后的內容,由于文件名作為字符串變量,這里基本都會超過8個字節,因此后面附加:$20。輸出結果如下:
五、混合輸入
在使用INPUT語句時不限于使用一種輸入方式,可以在一條INPUT語句中混合使用這些輸入方式,只要可以適當地描述原始數據記錄就行。
原始數據文件mixedinput.dat的內容如下,其中依次包括了課程編號、課程名稱、開課日期和報名人數等信息。
列表輸入讀取Course_ID和Attendee、按列輸入讀取Course_Name、格式化輸入讀取Open_Date。代碼如下:
跨行觀測值的讀取方式:
一般原始文件中一行代表一個觀測值,有時會出現一個觀測值跨行的情況。由于SAS會自動轉到下一行讀取數據,直到讀取這個觀測的所有變量(input語句中給出),所以你需要告訴SAS什么時候不要換行,以便在日志中不出現SAS-went-to-a-new-line的暫停說明,此時需要在INPUT語句中加行指示器。
行指示器,斜線/:告訴SAS跳至原始數據的第二行;#n:跳至第n行,n代表原始數據中某觀測值的行數(#2則讓SAS跳至某觀測值的第二行),#n不能用來回跳。
例子 有一組關于溫度的數據,temperature.dat第一行代表城市和州,第二行代表本日最高溫和最低溫,第三行代表史上最高溫和最低溫。
用如下的程度來讀取這份數據:
Input后面告訴SAS讀取第一行的city變量和state變量,斜線/告訴SAS移動到下一行的第一列,以便讀取normalhigh和normallow。#3告訴SAS移動到第三行的第一列以便繼續讀取觀測值的recordhigh變量和recordlow變量。這里/可以用#2代替,也可以用/代替#3。
日志記錄如下:
輸出結果如下:
一行有多個觀測值的原始文件讀取
當一行出現多個觀測值時,可以在input語句結尾加一個停止符號@@
例子 有一個關于降水量的數據,precipitation.dat,文件包含城市名、州名、月平均降水量、月平均降水天數:
這個數據文件中,第一行包含了兩個觀測值,可以用@@的程序讀取:
輸出結果如下:
讀取原始數據的部分觀測值
有時候只需要讀取原始數據的部分觀測值,比如只需要年鑒中的女性數據、收入超過10萬的人口數據等。此時的數據讀取方式如下:在SAS讀取某一行觀測值時,首先讀取足夠的變量以便決定是否需要保留此行的觀測值。然后在input語句結尾加符號@,叫做a trailing at(called a trailing at),這告訴SAS先停在(hold)此行,同時用IF語句檢測此觀測值是否滿足需要,如果是,那么可以再用一個input語句來讀取現有的變量。
例子 有一個關于當地交通的數據,traffic.dat數據包含街道的類型(freeways和surface)、街道名稱、早晨每小時的機動車流動量、晚上每小時機動車流動量。
如果現在你只需要freeway的數據,可以用下述程序:
第一個input讀取字符串變量,@是SAS停留在觀測值上并用IF檢測,第二個input讀取input后面的變量值。
輸入結果如下所示:
@ vs @@ ,@的作用類似于@@,都是行停留指示符(line-hold specifiers),不同地方在于停留多久,@能使SAS停留到下一個input語句(也不換行),@@能使停留的時間到下一個data步(也不換行)。
比如這段代碼:
data test;
infile cards ;
input x @;
input y;
input z @@;
cards;
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17
;
run;
test輸出結果就是:
****************************************************** The End ***************************************************
總結
以上是生活随笔為你收集整理的用SAS如何读取数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 审计一家言读后感
- 下一篇: B站首个千万级up主!论老番茄是如何炼成