機械学習用のデータセットをSASで作成していて、いろいろな加工を試したのでそのメモです。
日付操作
日付を表す数値8桁のカラムから日にちを取得する
例: 20240310 → 10 を取得
proc sql;
select
date, /* 数値8桁のカラム */
mod(date, 100) as day /* 末尾の2桁を取り出す */
from
table
;
quit;
日付型のカラムから日にちを取得する
例: 2024-03-10 → 10 を取得
proc sql;
select
date, /* 日付型のカラム */
day(date) as day /* 日にちの2桁を取り出す */
from
table
;
quit;
数値型の日付(YYYYMMDD形式)のカラムから指定した年月との月数の差分を計算
例: 202312 - 20230301 → 9
%let target_ym = 202312; /* YYYYMM形式 */
proc sql;
select
date, /* 数値8桁のカラム */
intck('month',
input(put(date, 8.), yymmdd8.),
input(put(&target_ym, 6.) || '01', yymmddn8.)) as month_diff
from
table
;
quit;
数値型の日付(YYYYMMDD形式)のカラムから指定した年月での年齢を計算
例: 202312 - 19920806 → 31
%let target_ym = 202312; /* YYYYMM形式 */
proc sql;
select
birthday,
int(yrdif(input(put(birthday, 8.), yymmdd8.), input(put(target_ym.01, 8.), yymmdd8.)), 'AGE') as age
from
table
;
quit;
日付変数の作成
※グローバル変数として定義するため以降のプロセスで利用可能
未来月
例: 2312 → yymm1after = 2401 ~ yymm12after = 2412
%macro create_future_dates(yymm);
%let year = %substr(&yymm, 1, 2);
%let month = %substr(&yymm, 3, 2);
%let base_date = %sysfunc(mdy(&month, 1, 20&year));
%do i = 1 %to 12;
%let future_date = %sysfunc(intnx(month, &base_date, &i, e));
%let future_yymm = %sysfunc(putn(&future_date, yymmn6.));
%global yymm_&i.after;
%let yymm_&i.after = %substr(&future_yymm, 3, 4);
%put yymm_&i.after = %substr(&future_yymm, 3, 4);
%end;
%mend create_future_dates;
/* 実行 */
%create_future_dates(2312);
過去月
例: 2312 → yymm1before = 2311 ~ yymm12before = 2212
%macro create_past_dates(yymm);
%let year = %substr(&yymm, 1, 2);
%let month = %substr(&yymm, 3, 2);
%let base_date = %sysfunc(mdy(&month, 1, 20&year));
%do i = 1 %to 12;
%let past_date = %sysfunc(intnx(month, &base_date, -&i, e));
%let past_yymm = %sysfunc(putn(&past_date, yymmn6.));
%global yymm_&i.before;
%let yymm_&i.before = %substr(&past_yymm, 3, 4);
%put yymm_&i.before = %substr(&past_yymm, 3, 4);
%end;
%mend create_past_dates;
/* 実行 */
%create_past_dates(2312);
文字列操作
数値型のカラムを取得し、頭に文字列をつけて連結し、文字列型として取得
例: 3 → num_3
proc sql;
select
catx('_', 'num', category) as category_str
from
table
;
quit;
文字列の数字を削除
例: 電話料金10月分 → 電話料金月分
data modified_data;
set original_data;
modified_column = kcompress(column_name, '01234567890123456789'); /* 前半の数字は半角、後半の数字は全角 */
run;
数値操作
傾きの作成(例として3変数)
m = \frac{N \sum (xy) - \sum x \sum y}{N \sum (x^2) - (\sum x)^2}
例: [100, 110, 120] → 10 / [15, 10, 5] → -5
proc sql;
select
user_id,
income1,
income2,
income3,
(3 * (sum(1*income1 + 2*income2, 3*income3)) - (sum(1+2+3) * sum(income1 + income2 + income3))) / (3 * sum(1*1 + 2*2 + 3*3) - (sum(1+2+3))**2) as income_slope
from
table
group by
user_id
;
quit;
その他
インデックス用のカラムを作成し連番を付与
data index_dataset;
set no_index_dataset;
index = _N_ ; /* 上から順番に1,2,3,,を付与する */
run;
作成したデータセットをCSVエクスポート
libname mylib 'C:\your\library\path';
proc export data=your_dataset
outfile='&mylib.\output.csv'
dbms=csv
replace;
run;
2つのデータセットが同一かを調べる(リファクタリング時など)
proc compare base=dataset_before compare=dataset_after;
run;