SAS數據清洗:sql
因爲SAS數據集之間的關係通常不會用到,只是在proc sql中有所涉及,至今還沒有運用過用於數據分析,因此在這裏只講單個數據集的處理。數組
在proc sql中咱們能夠看到:在定義數據集時涉及到字段名,字段屬性,字段標籤這三個最經常使用。咱們在數據清洗時涉及到的數據集字段的處理,主要也就是圍繞着字段名、字段屬性和字段標籤來進行處理。(對數據集結構的處理也就是對字段的增刪改)函數
修改數據集名稱和標籤(label)orm
增長字段很簡單,只須要在data步新建一個變量,對變量進行賦值便可。索引
刪除變量可使用drop和keep兩者二選一。rem
下面談一下最複雜的修改字段:字符串
修改字段名最簡單複雜的方法能夠利用增長字段和刪除字段兩者結合。而後就是用sas中的rename關鍵字進行處理,格式爲rename=(原字段名=新字段名)。input
修改字段的標籤:(定義label attrib label 變量名=label名)數據分析
修改使用modify 數據集名;label 變量名=label名。其中modify能夠用於修改rename format和label。string
修改sas的數據類型。
在sas中只有兩種數據類型:數值型和字符型。日期在sas中存儲形式是數值型,只是在顯示時使用日期的format顯示。
因此主要就是涉及到數值型和字符型之間的轉換
數值轉換爲字符:
data;
x=2557898;
y=put(x, $8.);
put y;
run;
字符轉換爲數值:
data;
x=2557898;
y=put(x, 8.); /* y=x-0;*/
put y;
run;
數值型和日期型之間的轉換主要就是利用日期的format,進行格式化的輸入和輸出。
SAS的日期時間都是數字型的,以便於計算。有各類格式能夠從數值轉變爲字符型。1960-01-01是日期的開始,SAS的日期是0. 以後天天加一。1960-01-02的值爲1. 1959-12-31的值爲-1. 以此類推。時間是一秒爲單位計算。從0(00:00:00)到86400(24:00:00)。每加一秒數值加一。
經常使用的日期時間轉換的function以下:
data _null_;
a=mdy(12,31,1959);
b='02jan1960'd;
c='24:00:00't;
d='00:00:00't;
e='31dec90:5:00:00'dt;
format e datetime18.;
put a= b= c= d= e=;
run;
a=-1 b=1 c=86400 d=0 e=31DEC90:05:00:00
data _null_;
x=1;
format x ddmmyy10.;
put x= ;
run;
output:
x=02/01/1960
字符串的處理:
對於全部的數據的處理無外乎增刪改查,雖然查在最後,但查是咱們應該作的第一件事。
查找:既對字符串的切片,查找出任何位置任意長度的子字符串。
1.得到字符串的長度:length(strings)
2.得到字符串中某子字符的索引:index(s,s1) .s1在s中出現的位置,能夠用於分割符的定位。
3.從固定的位置開始得到固定長度的字符串:substr(s,p,n). 從字符串s中的第p個字符開始抽取n個字符長的子串.
4.scan函數:scan(string,i,"char") 表示從字串string中以char爲分隔符提取第i個字串。其中char能夠是多個字符組合。
如:data work.test;
Title = 'A Tale of two Cities,Charles j.Dickens';
Word = scan(title,6,' ,');
put Word;
run;
output:Word=Charles
如下的例子很疑惑:
data a;
arg='abcdrf';
word=scan(arg,1);
put word=;
run;
output:word=abcdrf
不少資料顯示這個的結果應該是word=a,但實驗結果倒是word=abcdrf,不明白是哪裏不一樣?
data a;
arg='ABC.DEF(X=Y)';
word=scan(arg,2);
put word=;
run;
output:word=DEF
data a;
arg='ABC.DEF(X=Y)';
word=scan(arg,3);
put word=;
run;
output:word=X=Y
data a;
arg='ABC.DEF(X=Y)';
word=scan(arg,2,'.');
put word=;
run;
output:word=DEF(X=Y)
總結sas中scan函數在沒有定義分隔符的狀況下會有默認分隔符(已知:空格 . , ()等,可能全部的符合都是),在定了分割符後僅以此分隔符爲分割。Scan中的第二個變量即數字爲字符串被分割成多個子字符串後,所要查找的子字符串的索引(索引從1開始)。
5.Find函數:Pos=find(Text,'US','i',5),是要從第5個字符起找出US在源字符串Australia, US, Denmark中的起始位置,而且忽略大小寫。
find函數中四個參數,Text不用說,表明源字符串,若是直接引用的話須要用引號括起來;US,表明將要查找的字符,加引號;i,在這裏表示忽略大小寫;5,表示從第5個字符開始查找。
Notes:無論起始位置是多少,返回的位置數值始終是在源字符串中的位置。
6.Substr函數:(修改函數)
data _null_;
x=12345;
y=substr(x,1,2);
y1=substr(x,9,2);
z=substr(left(x),1,2);
put x= y= y1= z=;
run;
Output:x=12345 y= y1=23 z=12
y爲空的緣由是x爲數值型。y1爲字符型,9在這裏可能有特殊的含義。Left(x)後會轉化爲字符型。
字符替換(即所謂的右等):
data wb;
a='KIDNAP';
substr(a,1,3)='CAT';
put a;
run;
輸出結果:CATNAP
另一種狀況:
data wb;
a='KIDNAP';
substr(a,1,4)='CAT';
put a;
run;
結果爲:CAT AP
7. TRANWRD函數:(修改函數)
data convert;
input @1 address $20. ;
*** Convert Street, Avenue and
Boulevard to their abbreviations;
Address = tranwrd(Address,'Street','St.');
Address = tranwrd(Address,'Avenue','Ave.');
Address = tranwrd(Address,'Road','Rd.');
datalines;
89 Lazy Brook Road
123 River Rd.
12 Main Street
;
8.compress函數:(刪除函數)
Compress(String, characters-to-remove, optional-modifiers)
optional-modifiers:
例子:僅保留數字。
data Units;
input @1 Wt $10.;
Wt_Lbs =
input(compress(Wt,,'kd'),8.);
if findc(Wt,'K','i') then
Wt_Lbs = 2.2*Wt_Lbs;
datalines;
155lbs
90Kgs.
;
ouput:Wt_Lbs =155 198(英鎊)
字符串的鏈接有cat和’||’兩個:
data cat_catx;
length v_cats $6. v_catx $16.;
v_str1='CHI';
v_str2=' RAN';
v_str3='56789';
v_cats=cats(v_str1,v_str2);/*cats函數首先去掉每一個要鏈接字符串的首尾空格*/
v_catx=catx('/',of v_str1-v_str3);/*catx函數也去掉每一個要鏈接字符串的首尾空格,而且會在每一個字符串之間插入分隔符號*/
run;
cats和count組合:
data Survey;
input (Q1-Q5)($1.);
Num = countc(cats(of Q1-Q5),'y','i');
datalines;
yynnY
nnnnn
;
總結:經過length,substr(left=),index find,scan函數組合咱們能夠實現對字符串的切片。
經過substr和tranwrd能夠實現對字符串的修改。經過compress能夠實現對字符串內部的刪除,也會更改的一部分