개발로 자기계발
article thumbnail
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

 

열린데이터광장 메인

데이터분류,데이터검색,데이터활용

data.seoul.go.kr

웹사이트와 서버가 데이터를 어떻게 주고받는지 개발자도구의 Network를 통해서 확인한 API로 데이터 수집해 보았다.
그래서 url 주소가 더럽다...

https://github.com/seokcode/Seoul_High_Price_apt

 

GitHub - seokcode/Seoul_high_price_apt: 서울 자치구 별로 가장 매매값이 높은 아파트 선별(실거래가)

서울 자치구 별로 가장 매매값이 높은 아파트 선별(실거래가). Contribute to seokcode/Seoul_high_price_apt development by creating an account on GitHub.

github.com

folium.ipynb
0.00MB
seoul_map.html
0.08MB


코드 작성

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 

 

Google Maps Platform  |  Google Developers

Google Maps Platform 설명

developers.google.com

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
profile

개발로 자기계발

@김잠봉

틀린부분이나 조언이 있다면 언제든 환영입니다:-)