BSA05-Housing-Project.ipynb
필요한 패키지
import pandas as pd
import pyspark
from pyspark.sql import SparkSession
from sklearn.preprocessing import OneHotEncoder
from sklearn.impute import KNNImputer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import statsmodels.api as sm
import matplotlib.pyplot as plt
import folium
스파크 세션 시작 및 데이터 불러오기
스파크 = SparkSession.builder.appName('Test').getOrCreate()
스파크.conf.set("spark.sql.execution.arrow.enabled","true")
sparkDF = 스파크.read.csv("hdfs://localhost:9000/Spark/housing.csv", header=True, inferSchema="true")
sparkDF.show()
# Spark를 이용해 Hadoop data를 읽은 후 Pandas로 변환
# 판다스의 데이터프레임으로 만들고 '주택'으로 저장함
주택 = sparkDF.toPandas()
주택.info()
주택.describe()
※ 스파크 세션이 연결되지 않는 경우 ※
import os
import sys
os.environ['JAVA_HOME'] = "C:\Java"
os.environ['SPARK_HOME'] = "C:\spark-3.2.3"
os.environ['PYLIB'] = "C:\spark-3.2.3\python\lib"
sys.path.insert(0,os.environ['PYLIB']+"\py4j-0.10.9.5-src.zip")
sys.path.insert(0,os.environ['PYLIB']+"\pyspark.zip")
데이터 전처리
1. 범주형 데이터 → 더미변수 변환
# 결측값이 얼마나 있는지 확인 (True=1 : 결측값 / False=0 : 결측값이 아님)
주택.isna().sum()
# 결측값인 데이터들만 보이도록
주택[주택["total_bedrooms"].isna()]
# 'ocean_proximity'를 더미변수로
가변수처리 = OneHotEncoder()
해변가변수 = 가변수처리.fit_transform(주택[['ocean_proximity']])
해변가변수.toarray()
# numpy의 array를 dataframe으로 변환
가변수DF = pd.DataFrame(해변가변수.toarray(),columns=["I1","I2","I3","I4","I5"],index=주택.index)
가변수DF.head()
# 기존의 '주택' 데이터프레임과 '가변수' 데이터프레임을 결합
# 공통된 변수명이 없으므로 concat (axis=1)로 좌우(side-by-side)로 결합
# 기존의 '주택' 데이터프레임에 있는 'ocean_proximity'열 (마지막 열)은 '가변수' 데이터프레임의 정보와 겹치므로 제외하고 결합
새주택 = pd.concat([주택.iloc[:,0:-1],가변수DF],axis=1)
새주택.iloc[[290,341,538],]
2. 결측값 대체
1) k-nn
# weights="uniform" : 거리를 고려하지 않고 거리가 가까운 5개 데이터의 평균값으로 대체
# weights="distance" : 거리를 고려해 가까운 데이터에 가중치를 크게
근접대체 = KNNImputer(n_neighbors=5, weights="uniform")
# output은 pandas의 데이터프레임으로
근접대체.set_output(transform = 'pandas')
대체주택 = 근접대체.fit_transform(새주택)
대체주택.isna().sum()
# total_bedrooms = 242.6, 276.4, 1194.4, ... : 실수 형태로 대체됨 (평균 계산했기 때문)
# 'median_house_value'의 값이 크기 때문에 이 변수의 영향을 많이 받음
대체주택.iloc[[290,341,538],]
2) 표준화 후에 k-nn
평균 = 새주택.mean()
표준편차 = 새주택.std()
표준주택 = (새주택-평균)/표준편차
근접대체 = KNNImputer(n_neighbors=5, weights="uniform")
근접대체.set_output(transform = 'pandas')
표준대체주택 = 근접대체.fit_transform(표준주택)
표준대체주택.head()
# 표준화의 역작업으로 원래 스케일로 되돌림
대체주택 = 표준대체주택*표준편차+평균
대체주택.iloc[[290,341,538],]
회귀 모델 적용
1. sklearn - LinearRegression
# 설명변수, 반응변수 분리
X = 대체주택.drop("median_house_value",axis=1) # 설명변수
y = 대체주택["median_house_value"] # 반응변수
# 학습데이터, 검증데이터 분리
# test data의 비율이 30%이고, train data의 비율이 70%
train_X, test_X, train_y, test_y = train_test_split(X,y, test_size = 0.3, random_state=316)
# 선형회귀 모델 적합
선형회귀 = LinearRegression()
선형회귀.fit(train_X,train_y) # train data로 베타 추정
print("절편(bias):",선형회귀.intercept_)
print("회귀계수(weights):",선형회귀.coef_)
# train data로 적합시킨 모형으로 얻은 베타헷으로 test data에 적용해 예측값 얻음
예측값 = 선형회귀.predict(test_X)
print(test_y[0:10])
print(예측값[0:10])
# train data의 y와 test data의 y를 결합시켜 값의 분포를 확인하기 위해 두 데이터프레임 결합
# 데이터프레임의 한 열은 Series 형태임
비교 = pd.concat([pd.Series(list(test_y)),pd.Series(예측값)],axis=1)
비교.head()
# 시각화해서 그래프로 비교
# obs(관측값), pred(예측값) 컬럼명 설정
비교.columns = ["obs","pred"]
# scatterplot을 그림
# alpha=0.2 : 연하게
비교.plot(kind='scatter',x='obs',y='pred',alpha=0.2,figsize=(12,10))
plt.show()
2. statsmodels - OLS(ordinary least square)
# with statsmodels
# statsmodels에는 따로 옵션을 지정하지 않으면 베타0가 없음
# add_constant : 베타0도 계산하도록
train_X1 = sm.add_constant(train_X) # adding a constant
# OLS (ordinary least square) 방법
model = sm.OLS(train_y, train_X1).fit() # 베타헷 추정
# test data에도 베타0를 추가하는 작업이 필요함
test_X1 = sm.add_constant(test_X)
# 적합한 모델로 test data의 값 예측
pred = model.predict(test_X1)
비교 = pd.concat([pd.Series(list(test_y)),pd.Series(list(pred))],axis=1)
비교.head()
print_model = model.summary()
print(print_model) # 모든 변수가 유의함
데이터 시각화
주택.plot(kind='scatter',x='longitude',y='latitude',alpha=0.1,figsize=(12,10))
plt.show()
주택.plot(kind='scatter',x='longitude',y='latitude',alpha=0.4,s=주택['population']/100,label='population',
figsize=(12,8),c='median_house_value',cmap=plt.get_cmap('jet'),colorbar=True,sharex=False)
plt.legend()
plt.show()
folium 시각화
위도평균 = 주택["latitude"].mean()
경도평균 = 주택["longitude"].mean()
print("평균: 위도",위도평균,"경도",경도평균)
위도 = list(주택["latitude"])
경도 = list(주택["longitude"])
가격 = list(5*주택["median_house_value"]/주택["median_house_value"].max())
지도표시 = folium.Map(location=[위도평균,경도평균],zoom_start=9)
지도표시
# 주택 위치 CircleMarker로 표시
for i in range(0,100):
folium.CircleMarker([위도[i], 경도[i]]).add_to(지도표시)
지도표시
# 주택 가격에 따라 CircleMarker 크기 다르게 위치 표시
지도표시 = folium.Map(location=[위도평균,경도평균],zoom_start=9)
for i in range(0,1000):
folium.CircleMarker([위도[i], 경도[i]],radius=가격[i]).add_to(지도표시)
지도표시
#
지도표시 = folium.Map(location=[위도평균,경도평균],zoom_start=9)
for i in range(0,1000):
folium.CircleMarker([위도[i], 경도[i]],radius=가격[i],opacity=0.3,fill=True,fill_opacity=0.2).add_to(지도표시)
지도표시
#
지도표시 = folium.Map(location=[위도평균,경도평균],zoom_start=9)
for i in range(0,1000):
folium.CircleMarker([위도[i], 경도[i]],radius=가격[i],opacity=0.3,fill=True,fill_opacity=0.2).add_to(지도표시)
지도표시
# 'ocean_proximity' 그룹별로 색깔 다르게
주택위치 = list(주택['ocean_proximity'])
위치 = list(주택['ocean_proximity'].values)
지도표시 = folium.Map(location=[위도평균,경도평균],zoom_start=9)
for i in range(0,1000):
if 주택위치[i]==위치[0]: 색깔 = "red"
elif 주택위치[i]==위치[1]: 색깔 = "orange"
elif 주택위치[i]==위치[2]: 색깔 = "yellow"
elif 주택위치[i]==위치[2]: 색깔 = "green"
else: 색깔 = "blue"
folium.CircleMarker([위도[i], 경도[i]],radius=가격[i],color=색깔, opacity=0.3,fill=True,fill_opacity=0.2).add_to(지도표시)
지도표시
'Statistics > BSA' 카테고리의 다른 글
230426 / BSA08. 데이터 시각화 라이브러리 (0) | 2023.05.03 |
---|---|
230424 / BSA08. matplotlib 한글 처리 (0) | 2023.05.03 |
230417 / BSA05. 데이터 전처리 3 : 차원 축소 (0) | 2023.04.23 |
230417 / BSA05. 데이터 전처리 3 : 데이터 불균형, resampling (0) | 2023.04.23 |
230412 / BSA05. 데이터 전처리 2 : python, pyspark에서 데이터 결합 (0) | 2023.04.23 |