본문 바로가기
데이터 분석 및 시각화

[ML]클러스터링_집값 상관관계 분석해보기

by 바다의 공간 2024. 9. 11.

[File]
assets/rent.csv
clustering_df.py (
데이터프레임)
clustering.py
(클러스터링)

[Note]
clustering.txt


클러스터 : 군집화해놓은성질을 이야기 해놓음

그냥 단순히 모아놓는것이 아닌 특성이 비슷한 아이들을 모아놓은 작업을 클러스터링이라고 합니다.

 

하는 이유 : 

1. 매번 특성들을 분류하고 작업하기 힘듦

2. 연산의 편함을 위함

3. 새로운 특성이 있으면 클러스터에 포함가능


## 클러스터링(clustering)

* 클러스터(Cluster):  특성이 비슷한 것들
* 클러스터링(clustering): 특성이 비슷한 것들을 모은 것(군집)
* 클러스터링 목적
    - 더 빠른 연산 (매번 모든 데이터의 특성들을 분석해서 분류하고 연산하면 연산비 증가)
    - 새로운 특성을 가진 데이터가 새로 생기면 클러스터에 편입
    - 클러스터들을 모아서 더 거대한 클러스트들을 생성

 1. K-Means 클러스터링
    - 데이터들을 K개의 클러스터로 그룹화 하는 알고리즘
    - 각 클러스터들은 중심을 가지며 데이터 포인트는 가장 가까운 중심에 할당됨

  (1) 동작과정
        1) 클러스터의 중심점을 임의로 선택 (K가 의미하는 것은 클러스터의 수)
        2) 각 데이터 포인트를 가장 가까운 중심점에 할당
        3) 클러스터에 속한 데이터 포인트들의 평균을 계산하여 새로운 중심점을 갱신
        4) 중심점이 더 이상 변경되지 않을때까지 2,3번을 반복수행
        * 중심점이 더이상 변경되지 않는다 = 중심점이 확정되었다 = 다 모였다 = 클러스터 완성

 (2) 장점
    - 단순하면서도 효율적인 알고리즘
    - 대용량 데이터셋에서도 적용이 가능
    - 클러스터의 수를 지정하기 용이하다(K가 몇개다라고 지정하면 됨)

 (3) 단점
    - 클러스터의 모양이 원형이라고 가정하므로 다른 모양의 클러스터들을 잘 클러스터링하기 어렵다.
    - 초기 중심점의 위치에 따라 결과가 달라질 수 있으므로 초기화 방법에 따른 영향을 받을 수 있다
    (초기 중심점을 랜덤하게 뽑기 때문에 랜덤의 결과에 영향을 받을 수 있다.)

 (4) 공식
    - 중심점 계산 : 해당 클러스터에 속한 모든 데이터 포인트의 평균(mean)으로 계산
    - 중심점 = 클러스터 / 데이터 포인트의 개수
    - 데이터 포인트 할당 : 각 데이터 포인트는 가장 가까운 중심점에 할당
                        거리를 기반으로 할당 (유클리드 거리)
    - 거리(x, m) = n은 데이터 포인트의 차원 수,  xj = 데이터 포인트 x의 j번째 차원의 값




2. DBSCAN (Density-Based Spatial Clustering of Application With Noise)
    - 노이즈를 가진 밀도기반 클러스터링
    - 데이터 포인트 주변의 밀도를 기반으로 클러스터를 형성하는 알고리즘

    (1) 동작 과정 (ex: 태풍이 수분을 가져오는걸 생각하면 살짝 이해가 됨)
      1) 임의의 데이터 포인트를 선택한다
      2) 선택된 데이터 포인트에서 일정반경(epsilon)내에 있는 다른 데이터 포인트들을 찾음.
      3) 이웃 데이터 포인트의 개수가 최소개수(minPts)이상이면 해당 데이터 포인트들을 하나의 클러스터로 할당한다.
      4) 이웃데이터 포인트들도 반복적으로 클러스터에 추가하면서 클러스터를 확장시킨다.
      5) 클러스터에 포함되지 않은 데이터 포인트들은 노이즈(noise)처리한다.

    (2) 장점
      - 클러스터의 모양을 가정하지 않기 떄문에 다양한 모양의 클러스터를 찾을 수 있다.
      - 클러스터의 개수를 미리 지정할 필요가 없음
      - 노이즈를 처리할 수가 있어서 데이터에서 이상치를 식별할 수 있다.(멀리있는 노이즈를 버릴 수 있다)

    (3) 단점
      - 성능이 epsilon(반경), minPts(최소 인접 포인트개수),값에 따라 민감하게 반응할 수 있다.
      - 대규모 데이터셋 처리시 계산 비용이 증가할 수 있다

    (4) 공식
      - 거리계산을 사용(유클리드 거리)
      - 데이터 포인트간의 거리가 epsilon 이내인 경우 이웃 데이터 포인트로 판단
      - 나머지는 noise처리한다.


   



#rent 자료를 이용하여 데이터 분석 해보기

## clusterning_df.py

def p(str):
    print(str, '\n')

# 필요 라이브러리 로딩
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings(action='ignore')

# rent.csv 데이터 로딩
data = pd.read_csv('../assets/rent.csv')
data.info()

# rent.csv 파일 변수 설명
'''
 Posted On : 게시된 날짜
BHK 침실(Bedroom), 홀(Hall), 주방(Kitchen)의 수
Rent 임대료
Size 크기
Floor  층 수
Area Type 주택이 속한 지역의 유형
Area Locality 지역의 위치
City 도시의 이름
Furnishing Status 주택 또는 아파트의 가구 유무 상태
Tenant Preferred 선호하는 임차인 유형
Bathroom : 욕실 수
Point of Contact : 문의 할 담당자 
'''

#범주형 변수 분석
# p(data['Floor'].value_counts())
# p(data['Area Type'].value_counts())
# p(data['Area Locality'].value_counts())
p(data['City'].value_counts())

#컬럼명 변경
new_column_name = {
    "Posted On":"Posted_On",
    "BHK":"BHK",
    "Rent":"Rent",
    "Size":"Size",
    "Floor" : "Floor",
    "Area Type" : "Area_Type",
    "Area Locality" : "Area_Locality",
    "City":"City",
    "Furnishing Status":"Furnishing_Status",
    "Tenant Preferred":"Tenant_Preferred",
    "Bathroom":"Bathroom",
    "Point of Contact":"Point_of_Contact"}

data.rename(columns= new_column_name, inplace=True)

#BHK 값들을 오름차순으로 정렬
# data['BHK'].sort_values()

#Rent 확인
# p(data['Rent'].value_counts())
# p(data['Rent'].sort_values())

# 아웃라이어(이상치)
# 데이터 집합에서 다른 관측치들과 동떨어진
# 극단적인 값을 가지는 데이터 포인트

# # Rent boxplot
# plt.figure(figsize=(8,6))
# sns.boxplot(x=data['Rent'])
# plt.show()

# # Rent scatter
# plt.figure(figsize=(8,6))
# sns.scatterplot(x=data.index, y=data['Rent'])
# plt.show()

# BHK와 Rent의 상관관계 확인하기
corr_BR = data['BHK'].corr(data['Rent'])
# p(f'BHK와 Rent의 상관관계 : {corr_BR:.2f}')
#BHK와 Rent의 상관관계 : 0.37

# # 산점도 그래프 시각화 확인하기
# plt.scatter(data['BHK'], data['Rent'])
# plt.grid(True)
# # plt.show()
#
# # size확인
# p(data['Size'].value_counts())
# p(data['Size'].sort_values())

# # Size displot
# sns.displot(data['Size'])
# plt.show()
#
# # Size와 Rent의 관계
# plt.scatter(data['Size'],data['Rent'])
# plt.show()

# 1. 임대료와 BHK 상관관계
p(f"BHK와 임대료 상관관계 : {data['BHK'].corr(data['Rent'])}")
#BHK와 임대료 상관관계 : 0.3697175742804933

# 2. 임대료와 Size 상관관계
p(f"Size와 임대료 상관관계 : {data['Size'].corr(data['Rent'])}")
#Size와 임대료 상관관계 : 0.4135507582245195

#즉 Size가 상관관계가 좀 더 짙다 라고 볼 수 있습니다.

#3. 임대료와 도시별 상관관계

# 유일한 도시값 추출
cities = data['City'].unique()
# p(cities)

for city in cities:
    city_data = data[data['City']==city]

# 도시로 그룹핑한 후에 각 그룹들의 평균 임대료값
city_mean = data.groupby('City')['Rent'].mean()
# p(city_mean)

#도시는 문자이므로 수치형으로 변환해야 함
data['City_mean'] = data.groupby('City')['Rent'].transform('mean')
p(data['City_mean'])
#각 도시 랜트의 평균값으로 변경한 값으로 city_mean으로 넣어줌

#상관관계 확인
p(f'임대료와 도시별 평균 임대료의 상관관계: {data["Rent"].corr(data["City_mean"])}')
#임대료와 도시별 평균 임대료의 상관관계: 0.3322576943515555

# City, Rent 그룹과 Rent 상관관계
rent_city = data.groupby('City')['Rent'].corr(data['Rent'])
# p(rent_city)

# 도시목록 가져오기
cities = data['City'].unique()
p(cities)

# 도시별 임대료 상관관계
city_rent_corr = {}
for i in cities:
    city_data = data[data['City']==i]
    correlation = city_data['City'].corr(city_data['Rent'])
    city_rent_corr[i] = correlation
p(city_rent_corr)

# 수치형 데이터들로 heatmap 그리기

#수치형 변수만 선택
# numeric_data = data.select_dtypes(include=['int64', 'float64'])
# plt.figure(figsize=(10,8))
# sns.heatmap(numeric_data.corr(), annot=True)
# plt.show()

#지역별 임대료 분포 시각화
plt.figure(figsize=(10,6))
sns.boxplot(x='City', y='Rent', data=data)
plt.grid(True)
# plt.show()

#평균임대료 계산
avg_rent_city = data.groupby('City')['Rent'].mean().sort_values(ascending=False)
# p(avg_rent_city)

# #날짜데이터 변환
data['Posted_On'] = pd.to_datetime(data['Posted_On'])
data['Year'] = data['Posted_On'].dt.year
data['Month'] = data['Posted_On'].dt.month
# p(data['Year'].value_counts())
# p(data['Month'].value_counts())

# 월별 평균임대료
# 년 월로 그룹핑하기
avg_month_rent = data.groupby(['Year', 'Month'])['Rent'].mean()
p(avg_month_rent)


# #월별 평균임대료 시각화
# plt.figure(figsize=(12,6))
# avg_month_rent.plot(kind='line', marker='o')
# plt.grid(True)
# plt.show()

# 모델 선택
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
#mse

#필요한 컬럼 선택하기
features= ['BHK', 'Size', 'Floor', 'Bathroom']
data1 = data[features + ['Rent']]
p(data1)

# Floor 컬럼의 데이터 전처리 : 문자열에서 숫자만 추출하여 float로 변환하기
#1 out of 3
data1['Floor']= data1['Floor'].str.extract('(\d+)').astype(float)
p(data1)

# 결측치 처리
data1 = data1.dropna() #결측치가 있는 행 삭제
# data1.info()


# 훈련세트와 테스트세트 분리
X = data1[features]
y = data1['Rent']
X_train, X_test, y_train, y_test \
    = train_test_split(X, y ,test_size=0.2, random_state=42)

# 선형회귀 모델 만들기
lr = LinearRegression()

# 훈련 시키기
lr.fit(X_train, y_train)

# 예측값
pred = lr.predict(X_test)

# 평균제곱오차 (MSE)
mse = mean_squared_error(y_test, pred)
p(f"평균제곱 오차: {mse}")
#평균제곱 오차: 2542273917.555011

#실제값과 예측값 시각화해보기
plt.figure(figsize=(12,6))
plt.scatter(y_test,pred)
plt.plot(
    [min(y_test), max(y_test)], [min(y_test), max(y_test)],
    color = 'red',
    linestyle = '--'
)
plt.grid(True)
plt.show()

 

 

 

 

위 자료로 그려본 그래프들

 

Rent boxplot_이상치 확인하기

 

 

 

Rent scatter_ 이상치 확인하기

 

산점도 그래프 시각화 확인하기(grid=True)

 

Size displot

 

Size와 Rent의 관계
heat_map

 

위 그래프들을 통해서 상관관계를 확인 할 수 있습니다.

지역별 임대료 분포 시각화
월별 평균임대료 시각화(라인그래프 시각화)

 

 

실제값과 예측값 시각화해보기 예측선 만들어보기

 

 

 

 

 

 

 

 

순번 함수(매소드) 설명2
1 data.rename(columns= new_column_name, inplace=True) 컬렴명 재정의
2 데이터.sort_valies() 오름차순 정렬
3 .corr()  상관관계 결과를 찍어주는 함수
4 .transform() 수치형으로 변환하는 함수
5 .annot=True 수치표시
6 pd.to_datetime() 날짜로 변환
7 data1['Floor']= data1['Floor'].str.extract('(\d+)').astype(float) Floor를 실수로 변경해주는 함수