[COMPAS 광양시] 100x100 격자로 나누어져 있는 정보에 여러 정보들 추가로 합쳐보기! ( 주차장, 자동차등록현황, 건물(연면적), 개발행위제한구역, 행정경계, 고도)

솜씨좋은장씨

·

2020. 10. 25. 18:25

데이터 분석 활용 시간

2020년 10월 22일 9시 30분 ~ 11시 30분 ( 총 2시간 소요 )

 

사용 데이터

02.광양시_주차장_공간정보.csv

03.광양시_자동차등록현황_격자(100X100).geojson

17.광양시_건물분포도(연면적)_격자(100X100).geojson

20.광양시_행정경계(읍면동).geojson

23.광양시_개발행위제한구역.geojson

33.광양시_고도_격자(100X100).geojson

 

 

활용 코드

import os

file_list = os.listdir("./data")
file_list = file_list[:-4]
file_list = sorted(file_list)
for i, file in enumerate(file_list):
    print(i, file)
0 01.광양시_충전기설치현황.csv
1 02.광양시_주차장_공간정보.csv
2 03.광양시_자동차등록현황_격자(100X100).geojson
3 04.광양시_대중집합시설_생활체육시설.csv
4 05.광양시_대중집합시설_야영장.csv
5 06.광양시_전기차보급현황(연도별,읍면동별).csv
6 07.광양시_법정동별_인구현황(읍면동리).csv
7 08.광양시_격자별인구현황(100X100).geojson
8 09.광양시_버스정류장 및 택시승차장_공간정보.csv
9 14.광양시_소유지정보.geojson
10 15.광양시_건물정보.geojson
11 16.광양시_도로정보.geojson
12 17.광양시_건물분포도(연면적)_격자(100X100).geojson
13 18.광양시_법정경계(시군구).geojson
14 19.광양시_법정경계(읍면동).geojson
15 20.광양시_행정경계(읍면동).geojson
16 21.광양시_법정경계(리).geojson
17 22.광양시_연속지적.geojson
18 23.광양시_개발행위제한구역.geojson
19 24.광양시_도시계획(공간시설).geojson
20 25.광양시_도시계획(공공문화체육시설).geojson
21 26.광양시_도시계획(교통시설).geojson
22 27.광양시_도시계획(유통공급시설).geojson
23 28.광양시_도시계획(환경기초시설).geojson
24 29.광양시_산업단지(단지경계).geojson
25 30.광양시_산업단지(시설용지도면).geojson
26 31.광양시_산업단지(단지용도지역).geojson
27 32.광양시_DEM.img
28 33.광양시_고도_격자(100X100).geojson
29 34.코드정의서.xlsx

먼저 os.listdir을 활용하여 제공해준 모든 데이터 파일 목록을 불러왔습니다.

 

import pandas as pd
import geopandas as gpd
from shapely.geometry import Point, Polygon
from tqdm import tqdm

car_enroll_gdf = gpd.read_file("./data/" + file_list[2])
pop_info_gdf = gpd.read_file("./data/" + file_list[7])
building_gdf = gpd.read_file("./data/" + file_list[12])
godo_gdf = gpd.read_file("./data/" + file_list[-2])

이번 분석에서 필요한 라이브러리를 import하고 필요한 파일을 선정하여 해당 파일을 불러옵니다.

격자별 자동차 등록현황, 격자별 인구현황, 격자별 건물분포도, 격자별 고도정보를 불러왔습니다.

 

먼저 격자별 인구 현황과 격자별 건물 분포도의 gid, geometry 값이 같으므로 이를 바탕으로 하나로 합쳐줍니다.

pop_info_gdf = pop_info_gdf.fillna(0.0)
building_gdf = building_gdf.fillna(0.0)

pop_info_gdf.columns = ['gid', 'pop_val', 'geometry']

building_val = []

for i in tqdm(range(len(pop_info_gdf))):
    if pop_info_gdf['gid'].iloc[i] == building_gdf['gid'].iloc[i]:
        building_val.append(building_gdf['val'].iloc[i])

if len(building_val) == len(pop_info_gdf):
    pop_info_gdf['building_val'] = building_val
    
pop_info_gdf.head()

그 다음 나머지 정보들은 격자 정보가 다르게 나뉘어져 있으므로 

현재 인구현황과 건물분포도에 나뉘어져있는 격자정보들을 기준으로 다른 정보를 합치기 위하여 

그 기준으로 사용할 각 격자들의 중심좌표를 구하였습니다.

 

여기에는 shapely 라이브러리의 wkt method를 활용하였습니다.

from shapely import wkt 

center_points = []

for i in tqdm(range(len(pop_info_gdf))):
    center_point = wkt.loads(str(pop_info_gdf['geometry'].iloc[i])).centroid
    
    center_points.append(center_point)
    
if len(center_points) == len(pop_info_gdf):
    pop_info_gdf['center_point'] = center_points
    
pop_info_gdf

여기서 구한 중심 좌표를 기준으로 고도 정보와 자동차 등록현황 정보를 합쳐줍니다.

 

방법은 

각 격자의 중심좌표고도정보와 자동차 등록현황 정보의 격자안에 포함되는지 여부를 기준으로 판단하였습니다.

points = list(pop_info_gdf['center_point'])

car_enroll_list = []
godo_list = []

godo = list(godo_gdf['geometry'])
car_info = list(car_enroll_gdf['geometry'])

for i in tqdm(range(len(points))):
    point = points[i]
    gflag = False
    cflag = False
    
    for i in range(len(godo)):
        if godo[i].contains(point):
            godo_list.append(godo_gdf['DN'].iloc[i])
            gflag = True
            break
            
    if gflag == False:
        godo_list.append(None)

    for i in range(len(car_info)):
        if car_info[i].contains(point):
            car_enroll_list.append(car_enroll_gdf['totale'].iloc[i])
            cflag = True
            break
    if cflag == False:
        car_enroll_list.append(None)

if len(pop_info_gdf) == len(car_enroll_list):
    pop_info_gdf['car_enroll_val'] = car_enroll_list

if len(pop_info_gdf) == len(godo_list):
    pop_info_gdf['godo_val'] = godo_list

pop_info_gdf.head()

데이터를 봤을때 쉽게 볼수 있도록 column 값을 수정해주었습니다.

pop_info_gdf = pop_info_gdf.loc[: , ['gid', 'geometry', 'center_point', 'pop_val', 'building_val', 'car_enroll_val', 'godo_val']]
pop_info_gdf.columns = ['gid', 'geometry', '중심좌표', '격자별_인구현황', '격자별_건물분포도(연면적)', '격자별_자동차등록현황', '격자별_고도현황']
pop_info_gdf.head()

 

이번엔 제공해준 데이터를 바탕으로 각각의 격자가 개발행위허가제한지역인지 아닌지 여부를 판단해보았습니다.

limit_gdf = gpd.read_file("./data/" + file_list[18])
limit_gdf['DGM_NM'].unique()
array(['개발행위허가제한지역'], dtype=object)
limit_gdf

먼저 개발행위허가제한지역 정보가 담긴 파일을 불러온 다음 중심좌표를 기준으로 

해당 중심좌표가 개발행위허가제한지역에 포함되는지 여부를 파악해보았습니다.

 

limit_info = []

for i in tqdm(range(len(pop_info_gdf))):
    point = pop_info_gdf['중심좌표'].iloc[i]
    limit_flag = False
    
    for j in range(len(limit_gdf)):
        for poly in limit_gdf['geometry'].iloc[j]:
            if poly.contains(point) == True:
                limit_info.append(1)
                limit_flag = True
                break
    if limit_flag == False:
        limit_info.append(0)
        
len(limit_info)

pop_info_gdf['개발행위허가제한지역_여부'] = limit_info
pop_info_gdf

개발제한허가제한지역일 경우 1 그렇지 않을 경우 0으로 만들었습니다.

 

다음으로는 주차장 정보를 합쳐보기로 했습니다.

parking_spot_df = pd.read_csv("./data/" + file_list[1])
parking_spot_df

parking_dict = parking_spot_df.T.to_dict()
parking_dict

먼저 데이터를 불러온 후에 DataFrame을 to_dict()를 활용하여 dictionary로 바꾸었습니다.

{0: {'주차장명칭': '인동숲앞 주차장',
  '구분': '노외',
  '면적': 4189.0,
  '주차면수': 161.0,
  '유료/무료': '유료',
  '주소': '인서리 237-1',
  'lon': 127.5868828,
  'lat': 34.97032367},
 1: {'주차장명칭': '구터미널주차장',
  '구분': '노외',
  '면적': 2968.0,
  '주차면수': 125.0,
  '유료/무료': '유료',
  '주소': '중동 1651',
  'lon': 127.69542790000001,
  'lat': 34.936251899999995},
  ...

여기서 lon(경도)과 lat(위도) 정보를 활용하여 Point를 만들어 추가해줍니다.

from shapely.geometry import Point, Polygon

for i in range(len(list(parking_dict.keys()))):
    parking_point = Point(parking_dict[i]['lon'], parking_dict[i]['lat'])
    
    parking_dict[i]['point'] = parking_point
    
parking_dict
{0: {'주차장명칭': '인동숲앞 주차장',
  '구분': '노외',
  '면적': 4189.0,
  '주차면수': 161.0,
  '유료/무료': '유료',
  '주소': '인서리 237-1',
  'lon': 127.5868828,
  'lat': 34.97032367,
  'point': <shapely.geometry.point.Point at 0x7f1be3cf5be0>},
 1: {'주차장명칭': '구터미널주차장',
  '구분': '노외',
  '면적': 2968.0,
  '주차면수': 125.0,
  '유료/무료': '유료',
  '주소': '중동 1651',
  'lon': 127.69542790000001,
  'lat': 34.936251899999995,
  'point': <shapely.geometry.point.Point at 0x7f1be3cf54e0>},
  ...

이를 바탕으로 DataFrame에 추가합니다.

parking_spot_list_free = [0] * len(pop_info_gdf)
parking_spot_list_not_free = [0] * len(pop_info_gdf)
parking_spot_list = [0] * len(pop_info_gdf)

pop_info_gdf['주차장개수'] = parking_spot_list
pop_info_gdf['무료_주차장개수'] = parking_spot_list_free
pop_info_gdf['유료_주차장개수'] = parking_spot_list_not_free

parking_area_free = [0] * len(pop_info_gdf)
parking_area_not_free = [0] * len(pop_info_gdf)
parking_area = [0] * len(pop_info_gdf)

pop_info_gdf['주차면수'] = parking_area
pop_info_gdf['무료_주차면수'] = parking_area_free
pop_info_gdf['유료_주차면수'] = parking_area_not_free

parking_free = [0] * len(pop_info_gdf)
parking_not_free = [0] * len(pop_info_gdf)
parking = [0] * len(pop_info_gdf)

pop_info_gdf['주차면적'] = parking
pop_info_gdf['무료_주차면적'] = parking_free
pop_info_gdf['유료_주차면적'] = parking_not_free

for i in tqdm(range(len(list(parking_dict.keys())))):
    parking_point = parking_dict[i]['point']
    
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True:
            pop_info_gdf['주차장개수'].iloc[j] += 1
            break
            
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True and parking_dict[i]['유료/무료'] == '유료':
            pop_info_gdf['유료_주차장개수'].iloc[j] += 1
            break
            
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True and parking_dict[i]['유료/무료'] == '무료':
            pop_info_gdf['무료_주차장개수'].iloc[j] += 1
            break
            
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True:
            pop_info_gdf['주차면수'].iloc[j] += parking_dict[i]['주차면수']
            break
            
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True and parking_dict[i]['유료/무료'] == '유료':
            pop_info_gdf['유료_주차면수'].iloc[j] += parking_dict[i]['주차면수']
            break
            
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True and parking_dict[i]['유료/무료'] == '무료':
            pop_info_gdf['무료_주차면수'].iloc[j] += parking_dict[i]['주차면수']
            break
            
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True:
            pop_info_gdf['주차면적'].iloc[j] += parking_dict[i]['면적']
            break
            
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True and parking_dict[i]['유료/무료'] == '유료':
            pop_info_gdf['유료_주차면적'].iloc[j] += parking_dict[i]['면적']
            break
            
    for j in range(len(pop_info_gdf)):
        if pop_info_gdf['geometry'].iloc[j].contains(parking_point) == True and parking_dict[i]['유료/무료'] == '무료':
            pop_info_gdf['무료_주차면적'].iloc[j] += parking_dict[i]['면적']
            break

pop_info_gdf['주차장개수'].unique()
array([0, 1, 2, 4, 3])

각 격자별 주차장 개수는 0~4개 사이로 만들어진 것을 볼 수 있습니다.

마지막으로 행정경계 읍면동 정보를 합쳐주기로 했습니다.

umd_gpf = gpd.read_file("./data/" + file_list[15])
umd_gpf

umd_infos = []

for j in tqdm(range(len(pop_info_gdf))):
    umd_flag = False
    for i in range(len(list(umd_gpf['geometry']))):
#         print("나아님 : {}".format(umd_gpf['ADM_DR_NM'].iloc[i]))
        for poly in umd_gpf['geometry'].iloc[i]:
    #         print(poly)/
            if poly.contains(pop_info_gdf['중심좌표'].iloc[j]) == True:
#                 print("나임 : ",umd_gpf['ADM_DR_NM'].iloc[i])
                umd_infos.append(umd_gpf['ADM_DR_NM'].iloc[i])
                umd_flag = True
                break
    if umd_flag == False:
        umd_infos.append(None)

pop_info_gdf['행정경계_읍면동'] = umd_infos
pop_info_gdf.head()

 

이후에 다른 정보를 더 추가해보고 행정경계 읍면동 기준으로 합친 정보와 함께

최적입지 선정을 진행해보려합니다.

 

읽어주셔서 감사합니다.