728x90
Title
|
서울 자치구 별로 가장 매매값이 높은 아파트 선별(실거래가) |
tech | 1. 국가 data.co.kr에서 open api 수집 2. 데이터 전처리 3. Geocode를 이용하여 경도 위도 수집. |
Graph | 지도 그래프 및 마크 표현 |
Summary
|
자치구별 실거래가 최고가 아파트의 주변 환경을 분석하면 주변 아파트의 가격 시세도 파악 할 수 있을 것이다. |
※ 라이브러리는 제일 밑에서 정리
데이터는 공공데이터 포털의 서울시 부동산 실거래가 정보를 사용
https://data.seoul.go.kr/dataList/OA-21275/S/1/datasetView.do
웹사이트와 서버가 데이터를 어떻게 주고받는지 개발자도구의 Network를 통해서 확인한 API로 데이터 수집해 보았다.
그래서 url 주소가 더럽다...
https://github.com/seokcode/Seoul_High_Price_apt
코드 작성
1. 서울시 공공데이터 포털에서 서울시 부동산 실거래가 데이터를 수집한다.
def get_apt_data():
# 서울시 공공데이터 포털에서 부동산 실거래가 정보를 가져옴.
seoul_apt = []
for i in tqdm(range(1, page_number)):
# API를 호출하는 URL을 지정하고, requests 모듈을 사용하여 API를 호출함.
url = f"http://openapi.seoul.go.kr:8088/6364595a4b73736435336944534355/json/tbLnOpendataRtmsV/{(i-1)*1000+1}/{i*1000}/2022/%20/%20/%20/%20/%20/%20/%20/%20/%20/%EC%95%84%ED%8C%8C%ED%8A%B8/"
response = req.get(url)
# API에서 반환한 JSON 데이터에서 필요한 데이터를 추출하여 리스트에 추가함.
response_js = response.json()
row_data = response_js['tbLnOpendataRtmsV']['row']
for row in row_data:
# 아파트만 선별해서 가져온다.
data = {"자치구명":row['SGG_NM'],
"건물명":row['BLDG_NM'],
"매매가(만원)":row['OBJ_AMT']
}
seoul_apt.append(data)
# 추출한 데이터를 DataFrame으로 변환하고, '매매가(만원)' 열의 데이터 타입을 int로 변환함.
apt_df = pd.DataFrame(seoul_apt)
apt_df = apt_df.astype({'매매가(만원)':int})
return apt_df
한번 API로 데이터를 수집할 때 1000개로 한정되어 있기 때문에 for문을 돌면서 API를 요청한다.
URL 설명
{(i-1)*1000+1}/{i*1000} 부분으로 1000개씩 요청한다.
ex)
request1 -> (1, 1000)
request2 -> (1001, 2000)
json을 넣으면 json파일로, xml을 넣으면 xml파일로 데이터를 가져올 수 있다.
2. 가장 매매값이 높은 아파트 선별하기 위한 데이터 전처리
※ gmaps_key는 여기서 생성해서 삽입한다(mapks_key)
https://developers.google.com/maps?hl=ko
def apt_preprocessing():
apt_df = get_apt_data()
# 자치구별로 아파트 그룹화 후 기존 데이터와 일치 조건 생성
max_price = apt_df.groupby(['자치구명'])['매매가(만원)'].transform(max) == apt_df['매매가(만원)']
# 자치구별 매매가가 가장 비싼 아파트 선별
apt_max_df = apt_df[max_price]
# 데이터 중복제거
apt_max_df = apt_max_df.drop_duplicates(['건물명', '자치구명', '매매가(만원)'])
apt_max_df = apt_max_df.set_index("건물명")
# 구글맵 API를 사용하기 위한 키값을 입력
gmaps_key = "{gmaps_key}"
gmaps = googlemaps.Client(key=gmaps_key)
# iterrows는 DataFrame을 객체형식으로 데이터를 가져온다.
# idx는 index를 가져오고, rows는 idx의 행 값을 가져온다.
for idx,rows in apt_max_df.iterrows():
# geocode를 사용하기 위한 형식으로 바꿈
# {자치구}{아파트명}
# ex) 동작구한강현대, 강동구고덕그라시움, 광진구워커힐
borough = rows["자치구명"]+idx
borough_geocode = gmaps.geocode(borough, language="ko")
# 위도, 경도 좌표 가져오기
borough_lat= borough_geocode[0].get("geometry")['location']['lat']
borough_lng= borough_geocode[0].get("geometry")['location']['lng']
# 데이터 프레임에 삽입
apt_max_df.loc[idx, "lat"] = borough_lat
apt_max_df.loc[idx, "lng"] = borough_lng
return apt_max_df
3. google map 그리기
def get_apt_map():
apt_pre_df = apt_preprocessing()
# 서울 행정구역 json raw파일(githubcontent)
seoul_json = req.get('https://raw.githubusercontent.com/southkorea/seoul-maps/master/kostat/2013/json/seoul_municipalities_geo_simple.json')
seoul_json = seoul_json.content
seoul_json = json.loads(seoul_json)
# 서울시 자치구별 구분되어진 google map
seoul_map = folium.Map(
location=[37.559819, 126.963895],
zoom_start=11,
tiles='cartodbpositron'
)
# google map에 위에 위에서 만들어준 위도, 경도를 추가한다.
for i in range(len(apt_pre_df)):
folium.Marker(
[apt_pre_df["lat"][i], apt_pre_df["lng"][i]],
popup=f'{apt_pre_df.index[i]}'
).add_to(seoul_map)
folium.GeoJson(
seoul_json,
name='지역구'
).add_to(seoul_map)
# google map 로컬에 저장
seoul_map.save('./data/seoul_map.html')
# google map 시각화
display(seoul_map)
4. class화 시켜서 파이프라인 형식으로 리팩토링
import requests as req
import json
import pandas as pd
from tqdm import tqdm # 진행 상황을 나타내는 라이브러리
import folium # 지도 시각화 라이브러리
from folium import Marker
import googlemaps # Google Maps API 라이브러리
pd.options.display.max_rows = 50000
class AptPrice:
def __init__(self, page_number):
self.page_number = page_number
def get_apt_data(self):
# 서울시 데이터에서 아파트 실거래가 정보를 가져옴.
seoul_apt = []
for i in tqdm(range(1, self.page_number)): # 페이지 수 만큼 반복
# API URL을 생성하고 요청을 보냄
url = f"http://openapi.seoul.go.kr:8088/6364595a4b73736435336944534355/json/tbLnOpendataRtmsV/{(i-1)*1000+1}/{i*1000}/2022/%20/%20/%20/%20/%20/%20/%20/%20/%20/%EC%95%84%ED%8C%8C%ED%8A%B8/"
response = req.get(url)
response_js = response.json() # JSON 데이터로 변환
row_data = response_js['tbLnOpendataRtmsV']['row'] # 필요한 데이터 추출
for row in row_data:
data = {"자치구명":row['SGG_NM'],
"건물명":row['BLDG_NM'],
"매매가(만원)":row['OBJ_AMT']
}
seoul_apt.append(data) # 리스트에 데이터 추가
apt_df = pd.DataFrame(seoul_apt) # 데이터프레임으로 변환
apt_df = apt_df.astype({'매매가(만원)':int}) # 매매가(만원) 열의 데이터 타입을 정수형으로 변환
return apt_df
def apt_preprocessing(self):
apt_df = self.get_apt_data() # 아파트 실거래가 정보를 가져옴
max_price = apt_df.groupby(['자치구명'])['매매가(만원)'].transform(max) == apt_df['매매가(만원)']
apt_max_df = apt_df[max_price] # 자치구별로 가장 비싼 아파트 정보를 추출
apt_max_df = apt_max_df.drop_duplicates(['건물명', '자치구명', '매매가(만원)']) # 중복 데이터 제거
apt_max_df = apt_max_df.set_index("건물명") # 건물명을 인덱스로 설정
# Google Maps API를 사용하여 위경도 좌표 가져오기
gmaps_key = "YOUR_GOOGLE_MAPS_API_KEY"
gmaps = googlemaps.Client(key=gmaps_key)
for idx,rows in apt_max_df.iterrows():
borough = rows["자치구명"]+idx # 자치구명과 건물명을 조합하여 주소 생성
borough_geocode = gmaps.geocode(borough, language="ko") # 주소를 기반으로 위경도 좌표 가져오기
# 위경도 좌표 가져오기
borough_lat= borough_geocode[0].get("geometry")['location']['lat']
borough_lng= borough_geocode[0].get("geometry")['location']['lng']
apt_max_df.loc[idx, "lat"] = borough_lat # 위도 정보를 데이터프레임에 추가
apt_max_df.loc[idx, "lng"] = borough_lng # 경도 정보를 데이터프레임에 추가
return apt_max_df
def get_apt_map(self):
apt_pre_df = self.apt_preprocessing() # 아파트 실거래가 정보를 전처리
# 서울 행정구역 json raw파일(githubcontent)
seoul_json = req.get('https://raw.githubusercontent.com/southkorea/seoul-maps/master/kostat/2013/json/seoul_municipalities_geo_simple.json')
seoul_json = seoul_json.content
seoul_json = json.loads(seoul_json)
seoul_map = folium.Map(
location=[37.559819, 126.963895], # 지도의 중심 좌표 설정
zoom_start=11, # 지도의 초기 확대/축소 정도 설정
tiles='cartodbpositron' # 지도 스타일 설정
)
for i in range(len(apt_pre_df)):
folium.Marker(
[apt_pre_df["lat"][i], apt_pre_df["lng"][i]],
popup=f'{apt_pre_df.index[i]}' # 마커를 클릭하면 나오는 팝업 설정
).add_to(seoul_map) # 지도에 마커 추가
folium.GeoJson(
seoul_json,
name='지역구'
).add_to(seoul_map) # 지도에 지역구 경계 추가
seoul_map.save('./data/seoul_map.html') # 지도를 HTML 파일로 저장
display(seoul_map) # 지도 출력
if __name__ == "__main__":
apart_price = AptPrice(45) # 페이지 수를 45로 설정하여 객체 생성
apart_price.get_apt_map() # 지도 출력하기
728x90
SMALL
'Database & Data > 데이터 분석' 카테고리의 다른 글
데이터 크롤하고 분석(Seleniuum) - 5 (0) | 2023.04.20 |
---|---|
데이터 크롤하고 분석(정적 페이지와 동적 페이지) - 4 (0) | 2023.04.19 |
데이터 크롤하고 분석(BeautifulSoup) - 3 (0) | 2023.04.19 |
데이터 크롤하고 분석(Web Scraping 기초) - 2 (0) | 2023.04.18 |
데이터 크롤하고 분석(Web 기본 구조) - 1 (0) | 2023.04.17 |