보스턴 집값 분석 자료를 데이터 전처리와 새로운 변수 생성, 다양한 모델을 이용한 분석을 더 진행하고자 합니다.
'[ SAS 활용 노하우 ] 데이터 분석 2-1' 과 같이 Train / Test 데이터를 불러오고 Train 데이터 중 불필요한 변수를 제거합니다.
Test 데이터에 Train데이터의 전처리된 모든 내용을 그대로 수행해야합니다.
FILENAME REFFILE '/home/u45061472/sasuser.v94/boston_house_train.csv';
PROC IMPORT DATAFILE=REFFILE
DBMS=CSV
OUT=work.train;
RUN;
PROC CONTENTS DATA=work.train; RUN;
%web_open_table(work.train);;
RUN;
FILENAME REFFILE '/home/u45061472/sasuser.v94/boston_house_test.csv';
PROC IMPORT DATAFILE=REFFILE
DBMS=CSV
OUT=work.test;
RUN;
PROC CONTENTS DATA=work.test; RUN;
%web_open_table(work.train);;
RUN;
data work.train_1;
set work.train;
drop street alley utilities condition2 roofmatl bsmtfintype2 bsmtfinsf2 heating lowqualfinsf wooddecksf openporchsf poolarea poolqc miscfeature miscval miscval mosold yrsold;
run;
Proc sgplot은 다양한 그래프를 그릴 수 있습니다.
proc sgplot data = work.train_1;
histogram SalePrice;
density SalePrice / type = normal legendlabel='Normal' lineattrs=(pattern=solid);
density SalePrice / type = kernel legendlabel='Kernel' lineattrs=(pattern=solid);
keylegend / location = inside position = topright across = 1;
xaxis display=(nolabel);
run;
위와 같은 코드를 실행하면 그래프가 왼쪽으로 치우쳐 있는 것을 확인할 수 있습니다.
이럴 때 변수에 로그를 취하면 정규분포 값으로 모양이 변경됩니다.
스코어링을 할 때 로그를 취한 변수에 다시 지수함수를 원래 값으로 돌아오게 합니다.
data work.train_target;
set work.train_1;
N_SalePrice = LOG(SALEPRICE);
RUN;
proc sgplot data = work.train_1;
histogram N_SalePrice;
density N_SalePrice / type=normal legendlabel='Normal' lineattrs=(pattern=solid);
density N_SalePrice / type=kernel legendlabel='Kernel' lineattrs=(pattern=solid);
keylegend / location = inside position = topright across = 1;
xaxis display=(nolabel);
run;
로그를 취하면 다음과 같이 정규분포 모양으로 변형됩니다.
보스턴 데이터에는 비슷한 종류의 변수가 많아 변수끼리 결합하여 파생 변수로 더 좋은 결과를 낼 수 있습니다.
1. 외부컨디션 - 외부 컨디션에 해당하는 변수의 변형
ExterQual 은 외부 재료의 품질평가로
Ex - 5점 , Gd - 4점, TA - 3점, Fa - 2점, Po - 1점 , NA - 0점
ExterCond 는 외장재 재료의 현재 상태 평가로
Ex - 5점 , Gd - 4점, TA - 3점, Fa - 2점, Po - 1점 , NA - 0점
이 변수들을 결합하여 외부컨디션 변수를 생성하겠습니다.
data work.train_condition;
set work.train_target;
if ExterQual = 'Ex' then N_ExterQual = 5;
Else if ExterQual = 'Gd' then N_ExterQual = 4;
Else if ExterQual = 'TA' then N_ExterQual = 3;
Else if ExterQual = 'Fa' then N_ExterQual = 2;
Else if ExterQual = 'Po' then N_ExterQual = 1;
Else N_ExterQual = 0;
if extercond = 'ex' then n_extercond = 5;
else if extercond = 'Gd' then n_extercond = 4;
else if extercond = 'TA' then n_extercond = 3;
else if extercond = 'Fa' then n_extercond = 2;
else if extercond = 'Po' then n_extercond = 1;
else n_extercond = 0;
run;
면적 변수들을 결합하여 새로운 변수를 생성합니다.
TotalBsmSF : 지하실 총 면적
1stFlrSF: 1층 평방 피트
2ndFlrSF : 2층 평방 피트
GrLivArea : 지상 / 거실면적 편방피트
이 변수들의 산점도를 그려보면 이상치가 있었습니다.
그래서 간단한 처리를 통해 이상치를 제거하여 하였습니다.
data work.train_area;
set work.train_condition;
if totalbsmsf > 4000 or _1stflrsf >3000
or _2ndFlrsf > 1700 or Grlivarea > 4000 then delete;
run;
proc sgscatter data = work.train_area;
plot n_saleprice * (totalbsmtsf _1stflrsf _2ndflrsf grlivarea) / rows=10 columns=1;
run;
산점도를 그려보면 이상치가 제거된 것을 확인할 수 있습니다.
욕실에 대한 변수를 변형합니다.
BsmtFullBath : 지하 전체 욕실
BsmtHalfBath : 지하 반 욕실
FullBath : 등급 이상의 전체 욕실
HalfBath : 등급 이상의 절반 욕실
전체 욕실을 1로 반 욕실을 0.5로 정의하여 계산합니다.
FullBath가 0인 집이 0.62%인 것을 보면 대부분 화장실 1개씩 가지고 있었습니다.
빈도표 산출 코드와 전처리 코드는 다음과 같습니다.
proc freq data = work.train_area;
table bsmtfullbath bsmthalfbath fullbath halfbath;
run;
data work.train_bath;
set work.train_area;
bsmhalfbath = bsmthalfbath /2;
halfbath = halfbath/2;
run;
지하실에 대한 변수는 다음과 같습니다.
BsmtQual : 지하실 높이 평가
BsmtCond : 지하실 일반적인 상태 평가
BsmtExposure : 지하실 벽 노출 수준
BsmtFintype : 지하실 마감 면적 등급
proc sgscatter data = work.train_area;
plot n_saleprice * (bsmtqual bsmtcond bsmtexposure bsmtfintype1) / rows =10 columns=1;
run;
평가수준과 노출수준 등급에 따라 집값이 높아지는 추세를 확인할 수 있습니다.
지하실 상태 변수에 대한 전처리 코드는 아래와 같습니다.
data work.train_bsmt;
set work.train_bath;
if bsmtQual = 'Ex' then N_bsmtQual = 5;
Else if bsmtQual = 'Gd' then N_bsmtQual = 4;
Else if bsmtQual = 'TA' then N_bsmtQual = 3;
Else if bsmtQual = 'Fa' then N_bsmtQual = 2;
Else if bsmtQual = 'Po' then N_bsmtQual = 1;
Else N_ExterQual = 0;
if bsmtcond = 'ex' then n_bsmtcond = 5;
else if bsmtcond = 'Gd' then n_bsmtcond = 4;
else if bsmtcond = 'TA' then n_bsmtcond = 3;
else if bsmtcond = 'Fa' then n_bsmtcond = 2;
else if bsmtcond = 'Po' then n_bsmtcond = 1;
else n_bsmtcond = 0;
if bsmtexposure = 'Ex' then N_bsmtQual = 5;
Else if bsmtexposure = 'Gd' then N_bsmtexposure = 4;
Else if bsmtexposure = 'TA' then N_bsmtexposure = 3;
Else if bsmtexposure = 'Fa' then N_bsmtexposure = 2;
Else if bsmtexposure = 'Po' then N_bsmtexposure = 1;
Else N_bsmtexposure = 0;
if bsmtfintype1 = 'ex' then n_bsmtfintype1 = 5;
else if bsmtfintype1 = 'Gd' then n_bsmtfintype1 = 4;
else if bsmtfintype1 = 'TA' then n_bsmtfintype1 = 3;
else if bsmtfintype1 = 'Fa' then n_bsmtfintype1 = 2;
else if bsmtfintype1 = 'Po' then n_bsmtfintype1 = 1;
else n_bsmtfintype1 = 0;
run;
부지모양과 평탄도에 따른 변수는 다음과 같습니다.
LotShape : 부지모양 -> 평평함 -1 / 기울어짐 - 0
LandContour : 부동산의 평탄도 -> 평평함 -1 / 기울어짐-0
전처리 코드는 다음과 같습니다.
data work.train_land;
set work.train_bsmt;
if lotshape = 'IR1' then n_lotshape = 0;
else if lotshape = 'IR2' then n_lotshape = 0;
else if lotshape = 'IR3' then n_lotshape = 0;
else n_lotshape = 1;
if landcontour = 'bnk' then n_landcountour = 0;
else if landcontour = 'hls' then n_landcountour = 0;
else if landcontour = 'low' then n_landcountour = 0;
else n_landcontour = 1;
run;
차고 상태에 대한 변수는
GarageFinish : 차고 내부 마감
GarageQual : 차고 품질
GarageCond : 차고 상태 입니다.
차고 상태에 대한 변수는 집값과 상관성이 약간 있습니다.
proc sgscatter data = work.train_area; plot n_saleprice * (garagefinish garagequal garagecond) / rows = 10 columns=1; run;
data work.train_garage;
set work.train_land;
if garagefinish = 'FIN' then N_garagefinish = 3;
Else if garagefinish = 'rfn' then N_garagefinish = 2;
Else if garagefinish = 'unf' then N_garagefinish = 1;
Else N_garagefinish = 0;
if garagequal = 'ex' then n_garagequal = 5;
else if garagequal = 'Gd' then n_garagequal = 4;
else if garagequal = 'TA' then n_garagequal = 3;
else if garagequal = 'Fa' then n_garagequal = 2;
else if garagequal = 'Po' then n_garagequal = 1;
else n_garagequal = 0;
if garagecond = 'Ex' then N_garagecond = 5;
Else if garagecond = 'Gd' then N_garagecond = 4;
Else if garagecond = 'TA' then N_garagecond = 3;
Else if garagecond = 'Fa' then N_garagecond = 2;
Else if garagecond = 'Po' then N_garagecond = 1;
Else N_garagecond = 0;
run;
집에 대한 변수는 다음과 같다.
yearbuilt - 건축연도
yearremodadd - 리모델링 연도
리모델링 연도는 리모델링을 하지 않았을 때 건축연도와 값이 같습니다.
최신의 집과 리모델링한 집의 가격이 더 높아집니다.
2020년에 건축연도와 리모델링 연도를 뺀 뒤 두 값의 차를 2로 나누어 평균을 구하는 방법으로 새로운 변수를 만들 수 있습니다.
proc sgscatter data = work.train_area;
plot n_saleprice * (yearbuilt yearremodadd) / rows=10 columns=1;
run;
연속형 변수 중 Missing값을 가지고 있는 변수는 GarageYtBlt와 MasVnrArea입니다.
이 변수들의 결측치를 평균값으로 대체합니다.
GarageYrBlt - 평균값 1,978
MasVnrArea - 평균 값 101
proc means data = work.train_land;
var garageyrblt masvnrarea;
run;
연속형 변수와 그 외의 나머지 변수형 변수는 아래와 같이 처리합니다.
data work.train_other;
set work.train_garage;
if masvnrtype = 'NA' then masvnrtype = 'None';
if electrical = 'NA' then electrical = 'None';
if gargaetype = 'NA' then garagetype = 'None';
if garageyrblt = ' ' then garageyrblt = 1978;
if masvnrarea = ' ' then garageyrblt = 101;
if lotfrontage = 'NA' then lotfrontage = 0;
if fireplacequ = 'gd' then fireplacequ = 5;
else if fireplacequ = 'Gd' then fireplacequ = 4;
else if fireplacequ = 'TA' then fireplacequ = 3;
else if fireplacequ = 'Fa' then fireplacequ = 2;
else if fireplacequ = 'Po' then fireplacequ = 1;
else fireplacequ = 0;
if fene ='gdprv' then fence = 4;
else if fene ='mnprv' then fence = 3;
else if fene ='gdwo' then fence = 2;
else if fene ='mnww' then fence = 1;
else if fene ='na' then fence = 0;
else fence = 0;
run;
다음 데이터 분석 2-3에서는 모델 적합을 해보려고 합니다.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.