特别說明:本節【SAS Says】基礎篇:讀取資料(上),用的是數說君學習《The little SAS book》時的中文筆記,我們認為這是打基礎的最好選擇。
複習:
前面三節
- 【SAS Says】基礎篇:SAS軟體入門(上)
- 【SAS Says】基礎篇:SAS軟體入門(下)
- 【SAS Says】基礎篇:讀取資料(上)
前面在“基礎篇:讀取資料(上)”中我們介紹了list input的資料讀取方式,如果原始資料是用空格分隔的那麼可以用這種讀取方式,這種讀取方式要求變量值不能包含空格,并且不能跳過某些值,隻能用符号“.”來代表缺失。但是,當資料不是空格分隔的,或者沒用用句号代替缺失值,或者變量值中肯定要包含空格時怎麼辦?比如有一個address變量,大家知道位址中很多都帶有空格的,現在就有一個位址是“Columbia Peaches”,要怎麼讀取?别着急,本章中将介紹另外兩種讀取方式:column input和informats,以及如何同時利用這三種方式讀取資料。
此外,本節還要介紹如何處理那些淩亂的資料,如資料中出現不需要的亂碼如何不讀取、如何讀取某個特定字元後面的資料、如何讓SAS遇到空格就停止讀取等等。
本節目錄:
讀取資料(下)
2.6 column input讀取按固定排列的原始資料
2.7 informats讀取非标準格式的原始資料
2.8 用可選變量形式
2.9 混合讀取方式
2.10 讀取淩亂的原始資料
2.11 跨行觀測值的讀取方式
讀取資料(中)
2.6 column input讀取按固定列排列的原始資料
當一些原始資料的值之間沒有空格分開,或者沒用用句号代替缺失值時,list input就不能用。但當每個變量的值都出現在資料行的相同位置時,并且變量值是字元串或者标準數值(隻包含資料、小數點、正負号、和科學标注的E。逗号和日期都不能算)時,可以使用column input來讀取。
相比list input,column input有如下優勢:
- 不要求變量值之間的空格;
- 缺失值可以直接用空格代替;
- 字元串中可以包含空格;
- 可以跳過不需要的變量。
調查資料使用column input,因為調查答案的記錄都是用單個數字(0-9),如果每個答案之間再用空格分開,就會使整個檔案會擴大兩倍。有位址的資料檔案也使用 column input,因為位址之中常常包含空格,比如街道Martin Luther King Jr.Boulevard在column input中就可以當成一個變量而不是五個。可能用column input讀取的資料也可以用formattedinput讀取或者幾種方式組合。
Column input的input語句格式如下:input關鍵字後接變量名、再接變量的列位置(列位置是字元或者數值在一行中的位置)。字元串變量名後仍要用“空格+$”,變量名之間仍要用空格隔開。示例如下:

這個語句表明,Name變量,在行中占據第1列第10列,為字元串變量,age占據第11-13列,為數值變量,height占據第14-18列,數值變量。
例子 原始資料記錄如下:
讀取這個資料的column input程式如下:
第一個變量visitingteam占據第1-20列,為字元變量;concessionsales占據第21-24列,為數值變量,下面幾個變量均占據固定的列。輸出結果如下:
2.7 informats讀取非标準格式的原始資料
有時候原始資料不全是字元串或者數值,比如類似1,00,001這樣包括逗号的字元串值,電腦就不能讀取,其他諸如包含美元符号、十六進制、壓縮十進制的資料都是非标準資料。SAS中,informats可以用來告訴電腦如何讀取這樣的數值。
日期是最普通的非标準資料,SAS informats會把類似10-31-2003或者31OCT03轉換成數字,日期的起點為1960年1月1日,即這一天的數字為0。
Informats的三種普遍格式為:字元串、數值、日期。這三種格式的形式如下:
$代表是字元串、informats代表形式(比如日期的MMDDYY)、w是寬度、d是小數點的位數、最後是句号“.”,缺少句号會使得SAS把形式(如MMDDYY)當做變量名。一個簡單formatted input的簡單INPUT語句如下:
Name為字元串變量,占據10個寬度,即列位置從1-10;age為數值變量,占據3個寬度,列位置從11到13;height也為數值變量,占據5個寬度,包括了1位小數點和小數點本身,列位置從14-18(如150.3);最後是日期變量,從第19列開始,形式為MMDDYY。
例子 原始資料如下:
讀取這個資料的informat程式如下:
年齡後面的+1代表跳過一列,即原始資料中年齡後面有一個空格。最後的5個變量score1-score5,都要求有同樣的形式,4.1。将變量名和形式分别放在兩個括号集中,可以一次性定義很多變量。輸出結果如下:
2.8 可選擇變量形式
一般使用的變量形式的定義,以及它們的寬度範圍和預設寬度如下:
2.9 混合讀取方式
每種資料讀取方式都有其優勢,list最簡單,column和formatted雖然複雜但是不要求變量之間的空格,并且變量名中可以包含變量,而且formatted可以讀取特殊的資料比如日期。SAS可以靈活的讓你搭配不同的讀取方式,以達到最大的友善。
例子如下的原始資料記錄了美國國家公園的資訊:姓名(name)、所屬周(state)、建立時間(year established)、占地面積(size inacre):
有多種方式進行資料讀取,下面的程式是方式之一:
其中ParkName是column方式讀取,State和Year是list方式讀取,Acreage是formatted方式讀取,輸出結果如下所示:
混合讀取方式有時會遇到問題:SAS通過一個訓示器标注位置,來讀取原始資料的一行,但每種讀取方式對訓示器的使用稍有不同。List方式下,SAS自動找到非空格區域并開始讀取;column方式下,SAS讀取你所指定的特定位置;informatted方式下,SAS不理會訓示器的标準,隻是依次的讀取。這時,就會需要列訓示器@n,來人為的讓SAS的讀取直接跳至某列。
在上面的程式中,列訓示器@40告訴SAS在讀取Acerage變量之前,移動到第40列去,如果移去訓示器,程式為:
輸出結果如下圖所示:
之是以出現這樣的結果,要看原始檔案的列坐标排列:
Comma9告訴SAS讀取9列,SAS就會讀取包括空格在内的9列,這便會導緻輸出結果的問題。
2.10 讀取淩亂的原始資料
有的資料排列混亂,長度不一。這樣的資料需要新的工具處理:@’character’ 列訓示器和colonmodifier。
@’character’列訓示器 2.9中提到@column列訓示器可以讓SAS直接從某列開始讀取資料。但有時候你不知道要讀取的資料是從哪列開始,此時你隻要知道要讀取的資料的前面那個字元或單詞即可。比如有一個關于狗的原始檔案,你想要讀取狗的品種号,但檔案排列很淩亂,隻知道品種号跟随在單詞breed後面,那麼可以用如下方式讀取:
Input @’Breed:’ DogBreed $;
colonmodifier 由于input讀取字元串變量預設為8個字元,是以在上例中如果狗的品種名(dogbreed)超過8個字元,則需要定義長度,定義為$length,在該長度中,空格也算在内。如果要使SAS讀取過程中遇到空格則不再繼續讀取,則要在$length前面加冒号“:”。比如原始資料中有這麼一行:
My dog Sam Breed:Rottweiler VetBills:$478
如果用上述不同方法讀取,會有不同結果:
例子 web日志是淩亂資料的一個很好例子,下面是一個網站的web日志,資料開始于通路IP,後面有通路日期、通路檔案名等資訊。
現在想要讀取通路日期和通路的檔案名,但是它們每行中所占據的列的位置都不同,而且檔案名的長度每行都不一樣,那麼SAS讀取這種檔案通過如下方式:
@’[’作為列訓示器,告訴SAS讀取[之後的内容,@’GET’告訴SAS讀取GET之後的内容,由于檔案名作為字元串變量,這裡基本都會超過8個位元組,是以後面附加:$20。輸出結果如下:
2.11 跨行觀測值的讀取方式
一般原始檔案中一行代表一個觀測值,有時會出現一個觀測值跨行的情況。由于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。
日志記錄如下:
從日志中可以看出,雖然原始原件占了9行,但隻有三個觀測值。
輸出結果如下: