"빅데이터 분석 프로젝트" - 거주자우선주차구역 부정주차 해소

2022. 11. 1. 11:11빅데이터 분석 프로젝트

주제 : 거주자우선주차구역 부정주차 해소를 위한 계도활동 구간 선정

 

개요 : 효율적인 계도 활동 노선을 선정해 거주자 우선 주차구역의 활성화로 시민들의 생활 안정 도모


 데이터 분석 과정

  • 분석프로세스 정립
  • 울산광역시 중구 데이터 수집
  • 수집한 데이터 정제
  • 데이터 정제 후 주요 변수 추출
  • 주요 변수들을 이용한 군집분석
  • 최적 군집 선정
  • 선정된 행정구에 대한 Qgis 격자 생성
  • 순위에 따른 Folium 지도 맵핑
  • 최종 계도 구간 및 노선 선정

 데이터 분석프로세스


 데이터 수집 ( 기관 데이터와 공공데이터 위주로 파악하고 필요에 따라 민간데이터도 수집)

구분 활용 데이터 기간 제공기관
현황


데이터
울산광역시 중구 도시관리공단
거주자 우선 주차정보
2021 울산광역시 중구 도시관리공단
울산광역시 중구 도시관리공단
부정주차 단속 건수 (연도별)
2022 울산광역시 중구 도시관리공단
울산광역시 중구 도시관리공단
부정주차 단속 건수 (월별)
2022 울산광역시 중구 도시관리공단
울산광역시 중구 도시관리공단 부정주차 단속 건수 (시간대별) 2022 울산광역시 중구 도시관리공단
울산광역시 자동차등록대수
(2017~2022)
2022 KOSIS 국가통계포털
울산광역시 중구 읍면동별
자동차등록대수 현황
2022 울산광역시 차량등록사업소


위치

데이터

울산광역시 중구 공영주차장 개수 및 주차면수 2022 울산광역시 중구 도시관리공단
울산광역시 중구 주택현황.shp 2022 국가공간정보포털
울산광역시 중구 음식점 현황 2022 지방행정인허가데이터개방
인구
특성
울산광역시 중구 읍··동별_세대__인구 2022 KOSIS 국가통계포털
울산광역시 중구 격자별
생산 인구 수.shp
2022 국토정보플랫폼
 

 

 데이터 정제

 

 데이터 정제 과정

  1. Geo - Coding
  2. 필요한 데이터 칼럼 추출 및 삭제
  3. 데이터 실수화
  4. 중복값 및 결측값 처리
  5. 데이터 병합 (카운트, 합계)

 

 

 데이터 정제 일부 예시 코드

- 데이터 정제(그룹화 및 개수 결합)

#필요 라이브러리 
import pandas as pd
import numpy as np

#데이터셋 불러오기
df = pd.read_csv("./단속처리(정제).csv", encoding = 'cp949', engine = 'python')
df

#단속장소별 건수 확인

단속위치_groupby = df.groupby('단속장소').count()[df.columns[0]]
단속위치_groupby

#단속위치별 병합
df1 = pd.DataFrame(단속위치_groupby)
df1

#인덱스 재정렬
단속장소별_건수 = df1.reset_index()
단속장소별_건수

# 가장 단속이 많았던 위치 확인

단속장소df = 단속장소별_건수.iloc[단속장소별_건수["단속동"].idxmax()]
단속장소df

단속장소별_건수.to_csv("단속장소별_건수.csv", index = False, encoding = 'cp949')

 

- 데이터 병합

#데이터셋 불러오기
import pandas as pd
import numpy as np

df = pd.read_csv("./거주자우선주차구역(위치).csv", encoding = 'cp949', engine = 'python')
df

#데이터셋 불러오기
df1 = pd.read_csv("./단속장소별_건수.csv", encoding = 'cp949', engine = 'python')
df1

#데이터 병합
전처리_주차구역 = pd.merge(df, df1, on = '구획', how = 'left')
전처리_주차구역

#결측값 처리
전처리_주차구역.fillna(0, inplace = True)
전처리_주차구역

#데이터 타입 변경
전처리_주차구역 = 전처리_주차구역.astype({'단속건수' : 'int'})
전처리_주차구역

#데이터 저장
전처리_주차구역.to_csv("주차구역_결합.csv", index = False, encoding = 'cp949')

 

 

 변수 추출 ( 상관관계분석 및 변수 중요도 )

 

● 상관관계 분석 (동별)

import pandas as pd
import numpy as np
from matplotlib import pyplot
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import seaborn as sns

mpl.rcParams['axes.unicode_minus'] = False
mpl.rc("font", family = "Malgun Gothic")

df = pd.read_csv("./동별 전처리 데이터 개수결합.csv", engine = 'python', encoding = 'cp949')
df

df.corr(method='pearson')

df_corr = df
df_corr.corr()

sns.heatmap(df.corr(), annot=True, cmap = 'Reds')

동별 상관관계 분석

 

● 변수 중요도 (동별)

# 훈련 세트, 테스트 세트 분리 8:2 비율
import os
import pandas as pd
import numpy as np

from sklearn.model_selection import train_test_split

from matplotlib import pyplot
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
mpl.rcParams['axes.unicode_minus'] = False
mpl.rc("font", family = "Malgun Gothic")

df = pd.read_csv("./동별 전처리 데이터 개수결합.csv", engine = 'python', encoding = 'cp949')
df.head()

train_set, test_set = train_test_split(df, test_size=0.2, random_state=42)

senti_prepared = train_set[["구획개수","건물개수","주차면수합","인구수","자동차대수","음식점개수"]]
senti_label = train_set["단속건수"]

test_set_X = test_set[["구획개수","건물개수","주차면수합","인구수","자동차대수","음식점개수"]]
test_set_y = test_set["단속건수"]

from sklearn.ensemble import RandomForestRegressor

forest_reg = RandomForestRegressor(n_estimators=100, random_state=42)
forest_reg.fit(senti_prepared, senti_label)

answer = pd.DataFrame(test_set_y[:100].reset_index())
del answer["index"]

plt.plot(answer, label="answer")
plt.plot(forest_reg.predict(test_set_X[:100]), label="predict")
plt.legend()

from sklearn.metrics import mean_squared_error

senti_predictions = forest_reg.predict(senti_prepared)
forest_mse = mean_squared_error(senti_label, senti_predictions)
forest_rmse = np.sqrt(forest_mse)
forest_rmse


# 62.536199756620974

def plot_feature_importance(model):
    n_features = senti_prepared.shape[1]
    plt.barh(np.arange(n_features), sorted(model.feature_importances_), align="center")
    plt.yticks(np.arange(n_features), senti_prepared.columns)
    plt.xlabel("Random Forest Feature Importance")
    plt.ylabel("Feature")
    plt.ylim(-1, n_features)
    
plot_feature_importance(forest_reg)

동별 변수중요도

 

 군집분석 ( K-means )

 

● 비계층적 군집분석 ( K-means 분석 )

=> 6개의 변수를 2차원으로 차원축소하여 군집분석 진행, 군집개수는 K = 2로 확정

import pandas as pd
import numpy as np

np.random.seed(42)

from matplotlib import pyplot
%matplotlib inline

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

mpl.rcParams['axes.unicode_minus'] = False
mpl.rc("font", family = "Malgun Gothic")

df = pd.read_csv("./동별 전처리 데이터 개수결합.csv", encoding = "euc-kr")
df

df_raw = df[['소속동', '단속건수', '구획개수', '건물개수', '자동차대수', '주차면수합', '인구수', '음식점개수']]
df_raw

x = df_raw.drop(["소속동"], axis=1) # 독립변인 추출

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()

df_x = scaler.fit_transform(x) # 설명변수

from sklearn.cluster import KMeans

cluster_range = [i+1 for i in range(5)]
clus_error = []

for i in cluster_range:
    clus = KMeans(i)
    clus.fit(df_x)
    clus_error.append(clus.inertia_)
    
ds_error = pd.DataFrame({"NumberofCluster":cluster_range, "Error":clus_error})
ds_error

plt.figure(figsize = (10,5))
plt.plot(ds_error["NumberofCluster"], ds_error["Error"])
plt.title("Sum of squared distance")
plt.xlabel("Clusters")
plt.ylabel("Sum of squared distance")

np.random.seed(42)

kmeans = KMeans(n_clusters = 2).fit(df_x)
cluster_kmeans = [i+1 for i in kmeans.labels_]
df_raw["ClusterKmeans"] = cluster_kmeans
df_raw

print(cluster_kmeans)

kmeans.cluster_centers_

kmeans.labels_

df_raw["cluster"] = kmeans.labels_
df_raw.head()

from sklearn.decomposition import PCA
import plotly.express as px

#remember to scale your data if the ranges are too broad

# scaled_features= scaler.fit_transform(df) == df_x
# kmeans_model= KMeans(n_clusters=3, max_iter=500, random_state=42)

kmeans_model = KMeans(n_clusters = 2, random_state = 42)

y_km= kmeans_model.fit_predict(df_x)

pca_model= PCA(n_components=2, random_state=42)
transformed= pca_model.fit_transform(df_x)
centers= pca_model.transform(kmeans_model.cluster_centers_)

fig = px.scatter(x = transformed[:, 0], y = transformed[:, 1], color = y_km, text=df_raw["소속동"], title = "K-Means")
fig.add_scatter(
    x=centers[:, 0],
    y=centers[:, 1],
    marker=dict(size=10, color="red"), name="Centers",
)
fig.show()

 

군집분석 결과

* 위의 분석결과에서 추가적으로 복산2동 우정동 포함 (단속건수 빈도수에 가중치를 두고 주관적인 결정)  

 

 

 

 선정된 행정구에 대한 Qgis 격자 생성

● 동별 격자 생성 및 시각화 결과 1~4순위 구간 선정

행정동별 격자생성
격자 내 단속건수별 히트맵 시각화

 

 

순위에 따른 Folium 지도 맵핑

● 1~4순위 Folium 지도 시각화

1위 지도 맵핑
2위 지도 맵핑
3위 지도 맵핑
4위 지도 맵핑

 

 

 

최종 계도 구간 선정

● 1~4순위 계도 구간 시각화

1순위 계도 구간
2순위 계도 구간
3순위 계도 구간
4순위 계도구간

 

▶ 이번 프로젝트는 데이터 부족과 실현가능성이 많이 낮아서 분석의 신뢰도는 높지 않다.

하지만, 단속건수별로 데이터를 분석하여 정리해둔다면, 민원이 발생하기 전에 사전에 조치하여

중구민들의 삶을 증진하고 민원 발생률을  낮출 수 있을 것이다.