파이썬/ai

[ai, python] 인천광역시 집값 예측 프로젝트- 데이터 전처리 2

hojung 2022. 5. 18.
728x90
반응형

1. 공원 데이터 

앞선 포스팅에서 우리는 주택 특성 외 집 값에 영향을 미치는 변수들로 스타벅스, 대규모 점포, 병원, 학교, 근린공원, 반려동물 등록 수, 주변 지하철 역 개수 등을 선정했다. 

그 중 공원데이터를 얻기 위해서 나는 인천광역시 오픈데이터 사이트를 이용했다. 

대략 256개 정도 되는 데이터들을 일일이 다 분류한 후 같은 동끼리 개수를 count하는 작업을 수작업으로 진행하면 나는 오늘 하루를 버리고 말 것이다. 따라서 앞으로 처리해야할 데이터도 많기 때문에 파이썬의 openpyxl라이브러리를 사용해서 데이터를 전처리하고 새로운 엑셀 파일에 내가 원하는 (읍/면/동)별 공원의 도수 분포표를 만들기로 했다. 


2. 구현

이번에 받은 공원 데이터는 저번 대규모 점포 때와는 달리 .xlsx파일이 아닌 json형식으로 제공이 되었다. 

따라서 나는 json을 파싱한 후 원하는 데이터를 추출하기 위해 python에 내장되어 있는 json 라이브러리를 이용하였다. 

코드는 다음과 같다. 

import json
import openpyxl
import pandas as pd
import numpy as np
import re
wb = openpyxl.load_workbook("jsontest.xlsx", read_only=False, data_only=False)
ws = wb['Sheet1']

with open("park.json", "r", encoding="utf-8") as j:
    data = json.load(j)
var = []

for x in range(1, 256):
    name = data['features'][x]['attributes']['NAM']
    addr = data['features'][x]['attributes']["ADDR"]
    ws.cell(row=x, column=1).value = name
    ws.cell(row=x, column=2).value = addr
    # print(addr)


# w 동이 들어간 곳 추출
for x in range(1, 256):
    addr = data['features'][x]['attributes']["ADDR"]
    addrToken = addr.split(" ")
    for y in range(0, len(addrToken)):
        if(addrToken[y] == "동구" or addrToken[y] == "남동구" or addrToken[y] == "인천광역시동구"):
            continue
        if(addrToken[y].find("동") != -1):
            newToken = re.sub('[^a-zA-Zㄱ-힗]', '', addrToken[y])
            loc = newToken.find("동")
            newNew = newToken[0:loc+1]
            print("newToken: " + newNew)
            ws.cell(row=x, column=3).value = newNew
            var.append(newNew)
        ws.cell(row=x, column=4+y).value = addrToken[y]
print(var)
# print(pd.Series(var).value_counts())
print(np.unique(var, return_counts=True))
count = np.unique(var, return_counts=True)
print(count[0])
wb.save('jsontest1.xlsx')

우선 openpyxl의 load_workbook함수를 이용해서 엑셀 파일을 열고 json의 open함수를 이용해서 data변수에 json의 내용들을 집어 넣는다. 그 후 for문을 돌면서 json을 파싱해주었는데 

JSON

{
   "displayFieldName": "FTC",
   "fieldAliases": {
      "OBJECTID": "OBJECTID",
      "NAM": "NAM",
      "ADDR": "ADDR"
   },
   "geometryType": "esriGeometryPoint",
   "spatialReference": {
      "wkid": 4326,
      "latestWkid": 4326
   },
   "fields": [
      {
         "name": "OBJECTID",
         "type": "esriFieldTypeOID",
         "alias": "OBJECTID"
      },
      {
         "name": "NAM",
         "type": "esriFieldTypeString",
         "alias": "NAM",
         "length": 40
      },
      {
         "name": "ADDR",
         "type": "esriFieldTypeString",
         "alias": "ADDR",
         "length": 70
      }
   ],
   "features": [
      {
         "attributes": {
            "OBJECTID": 1,
            "NAM": "길쌈공원",
            "ADDR": "인천광역시 서구 연희동 668-6"
         },
         "geometry": {
            "x": 126.67585072237495,
            "y": 37.548009674568554
         }
      },
      {
         "attributes": {
            "OBJECTID": 2,
            "NAM": "갈마공원",
            "ADDR": "인천광역시 서구 심곡동 238-5"
         },

json 데이터가 다음과 같이 생겼으므로 ['features']에 들어있는 원소들에 접근하면서 ['attributes']의 ['NAM']과 ['ADDR']에 접근해서 추출한 후 저장해주었다. 

처음에는 그냥 모든 주소를 split함수를 이용해서 토큰화 한 뒤 토큰들을 탐색하며 "동"이 들어가면 그것을 (읍/면/동)으로 특정하려 했는데 인천에는 남동구와 동구 또한 존재하여 문제였다. 그래서 코드에서 남동구와 동구는 continue문을 통해 건너 뛰어 주었다. 또한 숭의1동 간석2동, 숭의동-83 등 중간에 숫자와 특수문자를 제거해주기 위해 python의 re를 통해 정규표현식을 통한 패턴 매칭을 해주었다.  그 후 

ws.cell(row=x, column=3).value에 찾은 토큰을 대입해주어 결과를 보았다. 

결과는 다음과 같이 잘 나왔고 위의 결과는 numpy를 이용해 중복되는 값을 없애고 unique 한 키값만 남긴 것이다. 

정상적으로 동이 들어가 있는 것을 확인할 수 있었다. 

728x90
반응형

댓글