|
(変数の定義) |
|
(演算子) |
|
(数値操作) |
|
(文字列操作) |
|
(日付操作) |
|
(型の変換) |
|
(ファイル操作) |
|
(CALLルーチン) |
|
|
本章は、データ操作に関するコードサンプルを例示しています。 |
|
(変数の定義) |
|
|
【変数の生成:暗黙的定義】
新しい変数を作成するには,等号の左辺にその変数をおいて,右辺の式の値を割り当てます
msg= ' メッセージ・・・・'; /*文字数は「最初に代入された文字の長さ」によって決定されます*/
【変数の明示的定義】
DATA ステップにおける変数の名前と型を明示的に定義します。
定義された変数は、DATA文で宣言する出力データセット(_NULL_は除く)のオブザベーションに追加されます。
ただし、DROPステートメントで指定した変数は追加されません。
DATA _NULL_;
LENGTH fname $ 100; /*100文字の文字型変数を明示的に定義 1〜32767バイトまで可能
*/
/*変数名の後ろに$を付けると文字型となる*/
LENGTH counter 4; /*4バイト長の数字型変数を明示的に定義 デフォルトは8バイト
*/
RUN; |
|
|
|
|
DATA ステップ中に定義した変数(文字型、数字型)は、各オブザベーションの処理の最初に、それぞれの型ごとに初期化(欠損値)されます。
ただし、RETAINステートメントで指定した変数は初期化されません。 |
|
|
(演算子) |
|
|
SASでは以下の四則演算子を用いることが出来ます。
|
|
+ |
加算 |
− |
減算 |
* |
乗算 |
/ |
除算 |
** |
べき乗 |
|
|
|
|
|
比較演算子は変数を値または他の変数と比較します。 |
|
= EQ |
等しい |
NE |
等しくない |
> GT |
より大きい |
< LT |
より小さい |
>= GE |
以上 |
<= LE |
以下 |
|
|
|
|
|
|
|
|
|
|
文字値を指定したパターンと比較します。
LIKE 'パターン'; |
|
% |
任意の文字数を置き換える |
_ |
1文字を置き換える |
|
|
|
(数値操作) |
|
|
SASでは関数を用いて計算を行うことがことが出来ます。関数は欠損値を計算の対象からはずして計算します。 |
|
SUM(引数1,引数2,・・・) |
合計値を求める |
MEAN(引数1,引数2,・・・) |
平均値を求める |
MAX(引数1,引数2,・・・) |
最大値を求める |
MIN(引数1,引数2,・・・) |
最小値を求める |
LARGEST(n, 引数1,引数2,・・・) |
n番目に大きい値を取得する |
ROUND(引数1,四捨五入の位置) |
四捨五入する |
ABS(x); |
絶対値 |
MOD(x,100); |
割り算の余りを返す |
SIGN(-156); |
符号を返す |
CEIL(x); |
整数値に切り上げ |
FLOOR(x); |
整数値に切り捨て |
INT(x); |
整数部分を取り出す |
|
|
|
(文字列操作) |
|
|
SASでは以下の関数を用いて文字列操作をすることが出来ます。 |
|
|
関数 |
処理 |
文法 |
使用例 |
CAT |
引数で指定した文字列(文字変数)を結合 |
CAT(変数1,変数2,・・,変数n); |
CAT(" aa "," bb ","
cc ")
結果:aabbcc |
CATS |
引数で指定した文字列(文字変数)を、それぞれの最初と最後に現れたブランクを取り除いて結合 |
CATX(変数1,変数2,・・,変数n); |
CATS(" a a "," b b ","
c c ")
結果:aab bcc |
CATT |
引数で指定した文字列(文字変数)を、それぞれの最後に現れたブランクのみを取り除いて結合 |
CATT(変数1,変数2,・・,変数n); |
CATS(" a a "," b b ","
c c ")
結果:aabbcc |
CATX |
引数で指定した文字列(文字変数)を、それぞれの最初と最後に現れたブランクを取り除き、
第1引数で指定したデリミタ(区切り文字)を付加して結合 |
CATX('-',変数1,変数2,・・,変数n); |
CATX(" a a "," b b ","
c c ")
結果:-aab bcc |
COMPRESS |
任意の文字を削除 |
COMPRESS(変数名,削除文字または文字列) |
x='A.B (C=D);';
y=compress(x,'.;()');
結果y:AB C=D |
COUNT |
文字列に含まれる任意の文字または文字列の出現回数をカウント |
COUNT(変数,'任意文字'); |
変数名='A1-100'
cnt=COUNT(変数名,'-'); |
LEFT |
左寄せ |
LEFT(変数名) |
a=' DUE DATE';
b=left(a);
結果b=DUE DATE |
MISSING |
文字変数、数値変数を問わず、欠損値を判定 |
MISSING(変数名) |
欠損値であれば1
そうでなければ0を返す |
RIGHT |
右寄せ |
RIGHT(変数名) |
a='DUE DATE ';
b=right(a);
結果b=DUE DATE |
INDEX |
文字列中の位置を求める
(合致した最初の位置) |
INDEX(変数名,bbb)) |
a='ABC.DEF (X=Y)';
b='X=Y';
x=index(a,b);
結果x=10 |
INDEXC |
文字列中の位置を求める
(1文字でも合致した最初の位置) |
INDEXC(変数,文字列,文字列n) |
a='ABC.DEP (X2=Y1)';
x=indexc(a,'0123',';()=.');
結果x=4 |
INPUT |
文字値を数値に変換する。
同様にSAS日付値にも変換する。戻り値は数値
変換に失敗した場合は欠損値が返される |
INPUT(元の変数,informat形式); |
prechar='50';
char1=INPUT(prechar,best12.);
best12.は適切な数値に変換するフォーマット
sas日付=INPUT(文字列, yymmdd6.); |
LENGTH |
文字列の長さを求める |
LENGTH(変数名) |
len=length('ABCDEF');
結果len=6
|
PUT |
指定したフォーマットで値を変換。戻り値は文字列 |
PUT(元の変数,format形式); |
num1=100
char1 = PUT(num1,Z5.);
Zw.dフォーマット
数値データの前にゼロをつけて出力。
wは全体の表示桁数(バイト数)、dは小数の桁数 |
REVERSE |
逆順に並べる |
REVERSE(変数名) |
backward=reverse('xyz ');
結果backward=zyx |
SCAN |
文字変数値の一部を抽出する |
SCAN(変数名,n,'文字列')
文字列で変数名の値を区切り、n番目の語を抽出 |
SCAN(id,1,'-');
idを'-'で区切り1番目の語を抽出
idの値がA-1のときAを抽出する |
SUBSTR |
b番目の文字から「c」文字分取り出す |
SUBSTR(変数名,bbb,cccc) |
a='KIDNAP';
substr(a,1,3)='CAT';
aの1-3文字を'CAT';に置き換える |
TRIM |
後ろの空白を削除 |
TRIM(変数) |
a='apple '
b='sauce '
noblank=trim(a)||b;
結果noblank=applesauce |
UPCASE |
大文字に変換 |
UPCASE(文字列変数) |
name=upcase('John B. Smith');
結果:JOHN B. SMITH |
VERIFY |
文字値の検証 |
VERIFY(検証文字 , '0123456789'); |
指定した文字以外の文字が出現する位置を戻し、指定する文字のみが存在する場合は「0」を戻す |
|
|
|
|
2バイト文字)に対応した関数
http://www.sas.com/offices/asiapacific/japan/service/technical/faq/list/body/ba184.html
関数と構文 |
機能 |
KCOMPARE(source, <pos, <count,>>
findstr) |
文字列の比較結果を返す |
KCOMPRESS(source <,characters-to-remove>) |
文字列から特定の文字を削除する |
KCOUNT(source) |
文字列内の2バイト文字の数を返す |
KINDEX(source, excerpt) |
文字式の文字列を検索する |
KINDEXC(source, excerpt-1<, ...excerpt-n>) |
文字式から特定の文字を検索する |
KLEFT(argument) |
不要な前置DBCSブランクとSO/SIを削除して、SAS文字式を左揃えにする |
KLENGTH(argument) |
引数の長さを返す |
KLOWCASE(argument) |
引数のすべての1バイト文字を小文字に変換する |
KREVERSE(argument) |
文字式を反転する |
KRIGHT(argument) |
後置DBCSブランクとSO/SIを削除して、文字式を右揃えにする
|
KSCAN(argument, n<, delimiters>) |
文字式から一定の語を選択する |
KSTRCAT(argument-1, argument-2<, ...argument-n>) |
2つ以上の文字列を連結する |
KSUBSTR(argument, position<, n>) |
引数から任意のDBCS部分文字列を抽出する |
KSUBSTRB(argument, position<, n>) |
バイト位置に基づく引数から任意のDBCS部分文字列を抽出する |
KTRANSLATE(source, to-1, from-1<, ...to-n,
from-n>) |
文字式に含まれる特定の文字を置換する |
KTRIM(argument) |
後置DBCSブランクとSO/SIを文字式から削除する |
KTRUNCATE(number, length) |
指定した長さに数値を切り捨てる |
KUPCASE(argument) |
引数のすべての1バイト文字を大文字に変換する |
KUPDATE(argument, position, n<, characters-to-replace>)
KUPDATE(argument,
position<, n>, characters-to-replace) |
文字値の内容を挿入、削除、置換する |
KUPDATEB(argument, position, n<, characters-to-replace>)
KUPDATEB(argument,
position<, n>, characters-to-replace) |
バイト単位に基づく文字値の内容を挿入、削除、置換する |
KVERIFY(source, excerpt-1<, ...excerpt-n>) |
式に固有な最初の文字の位置を返す |
|
|
|
|
|
|
文字列を結合は || (バーティカルバー)を用いて行います。
ex.
atena = sei || mei || ’さま’ |
|
|
|
|
SAS社FAQサイト Technical Support Frequently Asked Questions に記載があります |
|
|
|
|
Magazines :SAS Technical News Spring 2006 の「Q&A」を参照してください |
|
|
|
|
SAS9以降では、CALL MISSINGルーチンを使用して、複数の変数に欠損値をセットすることができます。
CALL MISSING(変数名1<,変数名2, ...>);
Magazines :SAS Technical News Summer 2005
の「Q&A」を参照してください |
|
|
|
|
SCAN関数を利用し文字変数値の一部を抽出します
準備中 |
|
|
|
|
文字変数、数値変数を問わず、欠損値を判定します
MISSING関数は、欠損値かどうかをチェックして、欠損値であれば1を、そうでなければ0を返します。
使用例
IF MISSING(変数名) THEN DO;
・・・
END; |
|
|
|
|
PRXMATCH関数を使用した正規表現による文字列のパターン検出
文法
PRXMATCH (regular-expression-id | perl-regular-expression,
source)
prxmatch : 戻り値は照合できた最初のバイト位置を返す
regular-expression-id ; 照合したい文字列の形式を指定したもの(Perl仕様の正規表現)
source : 文字列、変数
使用例
data _null_;
position=prxmatch('/world/', 'Hello
world!');
put position=;
run;
LOG結果 : position=7
よく使うパターン例
正規表現 |
内容 |
\d{3}-\d{4} |
文字列の形式は nnn-nnnn であること(nは数字) |
[0-9]{3}[-]{1}[0-9]{4} |
同上 |
[1-2][9|0][0-9][0-9]/[0-1][0-9]/[0-3][0-9] |
文字列の形式は YYYY/MM/DD であること(日付) |
\d+ |
文字列は すべて整数であること |
[^\x20-\x7E|ヲ-ン]+ |
文字列には 半角文字がないこと |
[0-9]?[0-9][0-9]\.[0-9] |
文字列の形式は nnn.n であること(身長) |
[0-9]{1,2}.[0-9]{1} |
文字列の形式は nn.n であること(体温) |
[0-9]?[0-9][0-9] |
文字列の形式は3桁以内の数字であること(血圧、脈拍数) |
[0-9]{1,3} |
同上 |
[0-9]{5} |
文字列の形式は5桁の数字であること |
00|15|30|45 |
文字列は00、15、30、45であること(分) |
[0-2][0-9]:[0-5][0-9] |
文字列は24時間表示の'hh:mm'という形式であること(時間) |
PRXCHANGE関数は正規表現による文字列の置換を行う
文法
PRXCHANGE(perl-regular-expression | regular-expression-id,
times, source)
正規表現の参考サイト |
|
|
(日付操作) |
|
|
関数 |
処理/文法 |
使用例 |
DATE |
今日の日付を返す(1960年1月1日を起点とした経過日数)、TODAYと同じ |
today=date(); |
DATEIF |
開始日付から終了日付までの日数を計算する
文法
日数= DATDIF(開始SAS日付値,終了SAS日付値,表示形式)
;
表示形式
ACT/ACT 年・月とも実際の日数で計算
30/360 1月を30日、1年を360日で計算
ACT/360 1月を実際の日数、
1年を360日で計算
ACT/365 1月を実際の日数、
1年を365日で計算 |
DATA _null_;
sdate = '16oct78'd;
edate = '16feb96'd;
actual = DATDIF(sdate, edate, 'act/act');
days360 = DATDIF(sdate, edate, '30/360');
PUT actual= ;
/* 実際の日数で計算*/
PUT days360= ; /* 1月を30日、1年を360日で計算*/
RUN ;
|
DATEJUL |
ジュリアン日付値表示から標準の日付値に変換 |
d=DATEJUL(2008366); |
DATEPART |
日時値から日付値部分を取り出す |
date=DATEPART("01JAN2008:12:10:00"DT); |
DATETIME |
現在の日時値を返す(1960年1月1日を起点とした経過秒数) |
now=DATETIME(); |
DAY |
日付値または日時値から日部分を取り出す |
day=DAY("10AUG2008"D); |
DHMS |
日付、時、分、秒から日時値を作成 |
val=DHMS("10AUG2008"D,12,10,30); |
HOUR |
時間値または日時値から時間部分を取り出す |
h=HOUR("01JAN2008:12:10:00"DT); |
INTCK |
開始時点から終了時点までの経過時間をさまざまな時間単位で計算 |
keika_month=INTCK"month","10JAN2008"D,"25AUG2008"D); |
INTNX |
SAS日付を年月の単位で移動させる
(nヶ月先の同日日付を取得する)
INTNX('MONTH',基準日付,1); /*1ケ月後の初日*/
INTNX('MONTH',基準日付,2); /*2ケ月後の初日*/ |
after=INTNX("month","10JAN2008"D,3,"END"); |
JULDATE |
日付値を5桁のジュリアン日付値形式(yyddd)に変換 |
juldate=JULDATE("01JAN2008"D); |
JULDATE7 |
日付値を7桁のジュリアン日付値形式(yyyyddd)に変換 |
juldate=JULDATE7("01JAN2008"D); |
MDY |
月、日、年から日付値を作成 |
date1=MDY(12,31,2007); |
MINUTE |
時間値または日時値から分部分を取り出す |
m=MINUTE("01JAN2008:12:10:00"DT); |
MONTH |
日付値または日時値から分部分を取り出す |
month=MONTH("01JAN2008:12:10:00"DT); |
QTR |
日付値または日時値から四半期部分を取り出す |
qtr=QTR("10AUG2008"D); |
SECOND |
時間値または日時値から秒部分を取り出す |
s=SECOND("01JAN2008:12:10:00"DT); |
TIME |
現在の時間値を返す |
now=TIME(); |
TIMEPART |
日時値から時間部分を取り出す |
time=TIMEPART("01JAN2008:12:10:00"DT); |
TODAY |
今日の日付を返す(1960年1月1日を起点とした経過日数)、DATEの別名 |
today=TODAY(); |
WEEKDAY |
日付から曜日を求める
文法
WEEKDAY(date)
dateはSAS日付値もしくはSAS日付値を表す式
戻り値
1 日曜日
2 月曜日
3 火曜日
4 水曜日
5 木曜日
6 金曜日
7 土曜日
|
DATA _NULL_;
date = '01apr2006'd;
day = WEEKDAY(date);
PUT day=;
RUN;
結果
day=7 |
YEAR |
日付値または日時値から年部分を取り出す |
year=YEAR("10AUG2008"D); |
YRDIF |
開始日付から終了日付までの年数を計算する
年数= YRDIF(開始SAS日付値,終了SAS日付値,表示形式)
;
表示形式
ACT/ACT 年・月とも実際の日数で計算
30/360 1月を30日、1年を360日で計算
ACT/360 1月を実際の日数、
1年を360日で計算
ACT/365 1月を実際の日数、
1年を365日で計算 |
DATA _NULL_;
sdate = '16oct1998'd;
edate = '16feb2003'd;
/* 1月を30日、1年を360日で計算*/
y30360 = YRDIF(sdate, edate, '30/360');
/* 実際の日数で計算*/
yactact = YRDIF(sdate, edate, 'ACT/ACT');
/* 1年を360日で計算*/
yact360 = YRDIF(sdate, edate, 'ACT/360');
/* 1年を365日で計算*/
yact365 = YRDIF(sdate, edate, 'ACT/365');
PUT y30360=
yactact=
yact360=
yact365= ;
RUN ; |
YYQ |
年、四半期から日付値を作成 |
yyq=YYQ(2008,1); |
|
|
※SASには、SAS日付値とSAS時間値およびSAS日時値という概念があります。日付値は、1960年1月1日を第0日として、1日ごとに1つずつ増えます。 |
|
|
|
|
年齢の計算には、INTCK関数を利用すると便利です。
INTCK関数は、二つのSAS日付値の間に何回、年(又は月)を越すかを求めるものです。
data _null_;
year=intck('YEAR', '31Dec1999'd, '1Jan2000'd);
put year=;
run; |
|
|
|
|
SAS社FAQサイト Technical Support Frequently Asked Questions に記載があります |
|
|
|
SAS日付を年月の単位で移動させる関数には、INTNX関数があります。
INTNX関数は、基準となる日付に対し、以下の構文で指定します。
INTNX('MONTH',基準日付,1); /*1ヵ月後*/
INTNX('MONTH',基準日付,2); /*2ヵ月後*/
monthafter = INTNX('MONTH',
'2011/12/25',
1) /*1ヵ月後*/
ただしINTNX関数は、デフォルトではnヵ月後の月の初日を返します。
したがって、nヵ月後の同日日付を求めるには少し工夫が必要になります。
DATA days;
INPUT hizuke YYMMDD10.;
CARDS;
2004/01/01
2000/02/29
2003/02/28
2004/12/02
2004/12/25
;
/* 1ヵ月後の日付計算 */
DATA temp;
SET days;
daydiff = DAY(hizuke)-1;
monthafter = INTNX('MONTH', hizuke, 1)
+ daydiff;
FORMAT hizuke YYMMDD8.
monthafter YYMMDD8.;
RUN;
与えられた基準日付 hizukeがその月の1日から何日後であるかを求め、daydiffに格納します。hizuke
が2004年11月26日ならば、daydiffは25となります。
Magazines :SAS Technical News Spring 2005
の「Q&A」を参照してください |
|
|
(型の変換) |
|
|
INPUT関数により、文字値を数値に変換することができます。
input(元の変数,informats);
var1=input(prevar1,best12.) /* best12.は適切な数値に変換するフォーマット
*/;
var2=input(prevar2,YYMMDDS10. .); /*
yyyy/mm/dd形式の日付を数値型に変換*/
informats の詳細はこちらを参照
以下でも良い
num = char + 0; または
num = char * 1;
|
|
|
|
|
PUT関数により、数値を文字値に変換することができます。
var1=put(prevar1,best12.) /* best12.は適切な文字値に変換するフォーマット
*/;
var2=put(prevar2,YYMMDDS10. .); /*
数値型の日付データをyyyy/mm/dd形式の文字値に変換*/
informats の詳細はこちらを参照
|
|
(ファイル操作) |
|
|
DATA _NULL_;
SET SASデータセット名;
IF _N_ = 1 THEN DO;
/* 1オブザベーション目のみ処理*/
lab_id = VLABEL(id); /* 変数idのラベル値を取得*/
lab_var = VLABEL(var); /* 変数varのラベル値を取得*/
END;
RUN; |
|
|
|
|
DATA _NULL_;
SET SASデータセット名;
IF _N_ = 1 THEN DO;
/* 1オブザベーション目のみ処理*/
type1 = VTYPE(id); /* 変数idの型を取得*/
type2 = VTYPE(var); /* 変数varの型を取得*/
END;
RUN;
数値変数の場合はN、文字変数の場合はCを、それぞれ戻り値として返します。 |
|
|
(CALLルーチン) |
|
|
DATAステップ変数の値をマクロ変数として作成し格納します。
マクロ変数はグローバル変数なので、プログラムのどこからでも参照できます。
CALL SYMPUTルーチンはDATAステップの機能です。
CALL SYMPUT('変数名',
設定値); /*変数名がマクロ変数として指定され、中身は設定値が入る*/
使用例
DATA _NULL_;
CALL SYMPUT('DATE',PUT(TODAY(),YYMMDD6.));
CALL SYMPUT('TIME',PUT(HOUR(TIME()),Z2.)||":"||PUT(MINUTE(TIME()),Z2.));
RUN;
※日付と時間をグローバル変数として取得しています。これでいつでも呼び出すことが可能になります。
マクロ変数の参照は、%DATE や %TIME として行います。
なお、CALL SYMPUTXルーチンで、マクロ変数作成時の前後のブランクを考慮するプログラムを簡素化できるようになっています。 |
|
|
|
|
複数の変数に欠損値をセットします。
CALL MISSING(変数名1<,変数名2, ...>); |
|
|
|
|