본문 바로가기
수업(국비지원)/Python

[Python] crime_in_Seoul.csv파일과 경찰관서 위치.csv파일 분석하기2

by byeolsub 2023. 4. 26.
########################
# 2022-12-14 복습
import numpy as np
import pandas as pd
# 서울 구별 CCTV 정보 데이터 읽기
CCTV_Seoul = pd.read_csv("data/01. CCTV_in_Seoul.csv")

# 서울시 경찰서별 범죄율 정보 데이터 읽기
crime_Seoul = pd.read_csv("data/02. crime_in_Seoul.csv",
                          thousands=',', encoding="cp949")
# 전국 경찰서 위치 데이터 읽기
police_state = pd.read_csv("data/경찰관서 위치.csv", encoding="cp949")

# police_Seoul 데이터에 서울청 데이터만 저장하기
police_Seoul =  police_state[police_state["지방청"] == '서울청']

# police_Seoul 데이터의 경찰서 컬럼의 내용을 
# xx서로 이름을 변경하여 관서명 컬럼으로 생성하기
police_Seoul["관서명"] = police_Seoul["경찰서"].\\
    apply((lambda x : str(x[2:] + '서')))

#1. police_Seoul 데이터에 지방청, 경찰서, 구분 컬럼 제거하기
del police_Seoul["지방청"],police_Seoul["경찰서"],police_Seoul["구분"]

#2. police_Seoul["관서명"] 중복행을 제거하기
# drop_Duplicates() 함수 사용
police_Seoul =\\
    police_Seoul.drop_duplicates(subset=["관서명"])

# police_Seoul 데이터의 주소 컬럼을 이용하여 구별 컬럼을 생성하기
# police_Seoul 데이터의 주소 컬럼 제거하기
#1-1
police_Seoul["구별"] = police_Seoul["주소"].apply((lambda x : str(x).split()[1]))

#2
del police_Seoul["주소"]

# 관서명을 연결컬럼으로 crime_Seoul, police_Seoul 데이터 병합하기
data_result = pd.merge(crime_Seoul, police_Seoul, on="관서명")

# 구별 범죄의 합계를 출력하기
crime_sum = data_result.groupby("구별").sum()

# 범죄 종류(강간,강도,살인,절도,폭력)별 검거율 컬럼추가 하기 
# 검거율 = 검거/발생 * 100
col_list = ['강간','강도','살인','절도','폭력']
for col in col_list :
    crime_sum[col + "검거율"] =\\
        crime_sum[col + " 검거"] / crime_sum[col + " 발생"] * 100
    print(crime_sum[col + "검거율"])    
crime_sum.info()    

# 검거율 데이터 중 100보다 큰값은 100으로 변경하기
for col in col_list :
    crime_sum.loc[crime_sum[col + "검거율"] > 100, col+"검거율"] = 100
    print(crime_sum[col + "검거율"])

 📌

# 구별 검거율과 CCTV 개수를 산점도와 회귀선으로 출력하기
# 오차가 큰 10개 구이름을 그래프로 출력하기

# crime_sum 인덱스를 구별 컬럼으로 변경하기
crime_sum.info()
crime_sum = crime_sum.reset_index()
crime_sum.info()

crime_sum 인덱스를 구별 컬럼으로 변경 전
crime_sum 인덱스를 구별 컬럼으로 변경 후

# 구별 컬럼으로 CCTV_Seoul, crime_sum 데이터를 병합하여 
# data_result 에 저장하기
CCTV_Seoul.info()

# 기관명 컬럼을 구별 컬럼명으로 변경
CCTV_Seoul.rename(columns={"기관명":"구별"},inplace=True)
CCTV_Seoul.drop(["2013년도 이전","2014년","2015년","2016년"],axis=1,inplace=True)

# cctv데이터 + crime 데이터를 구별로 병합
data_result = pd.merge(CCTV_Seoul, crime_sum, on="구별")
data_result.info()

# 절도검거율과 cctv 회귀선과 선점도 출력하기
fp1 = np.polyfit(data_result['소계'],data_result['절도검거율'],2) # 상수값
f1 = np.poly1d(fp1) # 회귀선을 위한 함수
fx = np.linspace(500,4000,100)

# data_result 데이터에 오차 컬럼을 추가하기
# 실제 검거율과 기대검거율의 차이의 절대값 저장
data_result["오차"] = np.abs(data_result["절도검거율"]-f1(data_result['소계']))

# 오차의 내림차순으로 정렬하여 df_sort 데이터 저장
df_sort = data_result.sort_values(by="오차",ascending=False)

import matplotlib.pyplot as plt
plt.rc('font', family='Malgun Gothic')
plt.figure(figsize=(8,8)) # 그래프 크기
# 산점도 : x축 : 소계, y축 : 절도검거율, 색상 : 오차
plt.scatter(df_sort['소계'],df_sort["절도검거율"],c=df_sort['오차'],s=50)
# 회귀선
plt.plot(fx, f1(fx), ls='dashed', lw=3, color='g')
# 해당 구이름 출력
for n in range(10) :
    plt.text(df_sort.iloc[n,]["소계"]*1.001, # x축의값
             df_sort.iloc[n,]['절도검거율']*0.98, # y축의 값
             df_sort.iloc[n,]['구별'],
             fontsize=10)
plt.xlabel('CCTV개수')
plt.ylabel('절도범죄 검거율')   
plt.title("CCTV와 절도 검거율 분석")
plt.colorbar()
plt.grid()
plt.show()

회귀분석


 📌

# 
'''
경찰서별 범죄발생 건수, CCTV 개수를 산점도와 회귀선으로 출력하기.
 단 CCTV의 개수는 구별로 지정한다.
 발생컬럼 : 모든 범죄 발생건수 합
    강도발생 + 강간발생 + 절도발생 + ...
'''
# 서울시 경찰서별 범죄율 정보 데이터 읽기
crime_Seoul = pd.read_csv("data/02. crime_in_Seoul.csv",
                          thousands=',', encoding="cp949")

# 발생 컬럼 생성하기
crime_Seoul["발생"] = crime_Seoul["살인 발생"] + crime_Seoul["강도 발생"] +\\
    crime_Seoul["강간 발생"] + crime_Seoul["절도 발생"] + crime_Seoul["폭력 발생"]

# 관서명을 연결컬럼으로 crime_Seoul, police_Seoul 데이터 병합하기
crime_Seoul = pd.merge(crime_Seoul, police_Seoul, on="관서명")
crime_Seoul

# 
crime_Seoul[["관서명","구별"]]

# cctv데이터 + crime 데이터를 구별로 병합
data_result = pd.merge(CCTV_Seoul, crime_Seoul, on="구별")

# 발생과 cctv 회귀선과 선점도 출력하기
fp1 = np.polyfit(data_result['소계'],data_result['발생'],1) # 상수값
f1 = np.poly1d(fp1) # 회귀선을 위한 함수
fx = np.linspace(500,3000,100)

# data_result 데이터에 오차 컬럼을 추가하기
# 실제 검거율과 기대검거율의 차이의 절대값 저장
data_result["오차"] = np.abs(data_result["발생"]-f1(data_result['소계']))

# 오차의 내림차순으로 정렬하여 df_sort 데이터 저장
df_sort = data_result.sort_values(by="오차",ascending=False)

import matplotlib.pyplot as plt
plt.rc('font', family='Malgun Gothic')
plt.figure(figsize=(8,8)) # 그래프 크기
# 산점도 : x축 : 소계, y축 : 절도검거율, 색상 : 오차
plt.scatter(df_sort['소계'],df_sort["발생"],c=df_sort['오차'],s=50)
# 회귀선
plt.plot(fx, f1(fx), ls='dashed', lw=3, color='g')
# 해당 구이름 출력
for n in range(10) :
    plt.text(df_sort.iloc[n,]["소계"]*1.001, # x축의값
             df_sort.iloc[n,]['발생']*0.98, # y축의 값
             df_sort.iloc[n,]['관서명'],
             fontsize=10)
plt.xlabel('CCTV개수')
plt.ylabel('범죄 발생건수')   
plt.title("CCTV와 범죄발생건수 분석")
plt.colorbar()
plt.grid()
plt.show()