수업에서 실습을 할 때 주식 및 금융 데이터로 분석을 했었기 때문에 그렇다면 부동산을 해볼까?는 생각으로 '부동산 데이터' 로 설정하고 스크랩핑 및 EDA 분석을 진행하기로 했다.
대부분의 부동산 데이터들이 지도상에 표기가 되어 있어서 스크랩핑을 할 수 없었다.
스크랩핑 할 수 있는 데이터를 찾다가 부동산 경매 데이터를 찾게 됐다.
https://auction.realestate.daum.net/v15/

개발자도구에서 network 탭을 통해서
해당 화면에서 더보기를 눌렀을 때 url 을 확인 했다.
해당 url 은 post 방식으로 호출 하고 있는 걸 확인 할 수 있다.

# 필요한 라이브러리 설정
import pandas as pd
import numpy as np
import requests
import time
import matplotlib.pyplot as plt
import seaborn as sns
# auction 데이터를 가져와서 파일로 저장하는 함수
def get_auction_list():
json_list = []
for page_no in range(50):
# url 준비
page_no += 1
addr1="서울"
url = f"https://auction.realestate.daum.net/ajax/main_mulgun_list.php?pcode=1100000000&yongdo=99&yongdo_detail=99&result=99&x1=126.54771398007276&y1=37.830109247353455&x2=127.47653798540581&y2=37.30777582941757&maplevel=10&lvm=3&pg={page_no}&sort=12&lat=37.56986202081117&lng=127.01050451138688&addr1={addr1}&total=1273"
# 데이터 받아오기
response = requests.post(url)
# json data 로 만들기
json_data = response.json()
# json data를 리스트로
list_temp = json_data["rtn"]["list"]
json_list.extend(list_temp)
time.sleep(0.1)
# 리스트를 dataFrame 으로
df_auction = pd.DataFrame(json_list)
# 컬럼 정리
df_auction = df_auction.drop(["num", "bubcd", "sano2", "sano1", "mul_seq", "tget", "im", "image"], axis=1)
#파일 이름 만들기
file_name = "auction.csv"
#파일로 저장
df_auction.to_csv(file_name, index=False, encoding="cp949")
return file_name
# 함수 호출하기
file_name = get_auction_list()
# 파일 불러오기
df = pd.read_csv(file_name, encoding="cp949", thousands = ',')
df

감정가(gamp)와 최저가(lowp) 차이로 diff 라는 파생변수를 만들었다.
df["diff"] = df['gamp'] - df['lowp']
df.info()

df.isnull().sum()

df.shape # (500, 12)
# 중복값 확인 및 제거
df.duplicated()
df = df.drop_duplicates()
df.shape # (483, 12)
결측치 제거 후 17개만큼 데이터가 줄어든 것을 확인 할 수 있다.
df.dtypes

df.describe()

df.describe(include=["object"])

df.nunique()

# addr2 의 빈도수 구하기
df["addr2"].value_counts()
# yongdo 의 빈도수 구하기
df["yongdo"].value_counts()

# gamp 의 이상치 찾기
gamp_q1 = df["gamp"].quantile(0.25)
gamp_q3 = df["gamp"].quantile(0.75)
IQR = gamp_q3 - gamp_q1
print(gamp_q3 + 1.5*IQR) # -> 804500000.0
print(gamp_q1 - 1.5*IQR) # -> -159500000.0
# outline 보다 큰 값들을 확인한다.
large = df["gamp"] > gamp_q3 + 1.5*IQR
# outline 보다 큰 값들의 index 를 확인한다.
index_outlayer = df[large].index
# 해당 index 를 삭제한다.
df_clean = df.drop(index_outlayer)
df.shape # -> (483, 12)
df_clean.shape # -> (402, 12)
plt.figure(figsize=(16,15))
sns.boxplot(data=df, x="addr2", y="gamp")

plt.figure(figsize=(16,15))
sns.boxplot(data=df_clean, x="addr2", y="gamp")

plt.figure(figsize=(16,15))
sns.barplot(data=df, x="addr2", y="gamp", ci=None)

plt.figure(figsize=(16,15))
sns.barplot(data=df_clean, x="addr2", y="gamp", ci=None)

plt.figure(figsize=(12, 4))
sns.stripplot(data=df, x="addr2", y="gamp")

plt.figure(figsize=(12, 4))
sns.stripplot(data=df_clean, x="addr2", y="gamp")

df.hist(bins=50, figsize=(16,10))
plt.show()

df_clean.hist(bins=50, figsize=(16,10))
plt.show()

plt.figure(figsize=(16,15))
sns.distplot(x = df["gamp"], kde=True, rug=True)

plt.figure(figsize=(16,15))
sns.distplot(x = df_clean["gamp"], kde=True, rug=True)

!pip install pandas_profiling
from pandas_profiling import ProfileReport
# 이상치 제거 전
profile = ProfileReport(df)
profile.to_file("pandas_profile_report_auction.html")
# 이상치 제거 후
profile = ProfileReport(df_clean)
profile.to_file("pandas_profile_report_auction_clean.html")


이상치 제거 전
이상치 제거 전
왜도도 많이 줄고, 첨도는 기하급수적으로 줄어든 걸 볼 수 있다. 그리고 평균도 반 이하로 낮아졌다.
이상치를 제거 한 이후의 데이터 시각화 결과와 분석이 너무나 달라지는 걸 확인 할 수 있었다.
# e 로 숫자 쓰여지지 않게 설정
pd.options.display.float_format = '{:.5f}'.format
df.groupby(["addr2", "addr3"]).mean()

df.groupby(["yongdo"])["gamp", "lowp", "diff"].mean()

groupby 를 했는데도 종류가 많아서 알아보기 힘든 문제가 있다.
df_temp = df[df["yongdo"].isin(["다세대","아파트","오피스텔"])]
df_temp = df_temp[df_temp["addr2"].isin(["강남구", "서초구", "관악구", "강서구", "은평구", "금천구"])]
df_temp = df_temp.reset_index(drop=True)
df_temp
# groupby
pd.options.display.float_format = '{:.5f}'.format
df_temp.groupby(["addr2"])["gamp", "lowp", "diff"].mean()

# 전체
plt.figure(figsize=(16,15))
sns.barplot(data=df_clean, x="addr2", y="diff", ci=None)
# 일부
plt.figure(figsize=(16,15))
sns.barplot(data=df_temp, x="addr2", y="diff", ci=None)


# 전체
plt.figure(figsize=(16,15))
sns.countplot(data=df, x="addr2", hue="yongdo")
# 일부
plt.figure(figsize=(16,15))
sns.countplot(data=df_temp, x="addr2", hue="yongdo")


전체에서는 각 지역별 용도를 알고 싶지만 용도가 너무 종류가 많아서 확인하기 쉽지 않다.
원하는 지역에서 비교하고 싶은 용도만을 비교할 수 있다.
대체로 다세대의 비율이 압도적으로 높다.