Python/Study

[Python] 서울 5대 범죄 현황 분석

Yoppie 2024. 1. 20. 12:31
반응형
import pandas as pd
import numpy as np
In [2]:
# 데이터 불러오기
In [3]:
cctv = pd.read_csv('서울cctv.csv')
In [4]:
pop = pd.read_csv('서울인구.csv')
In [5]:
crime = pd.read_csv('서울범죄.csv',encoding='utf-8')
In [6]:
cctv.head()
Out[6]:
 
In [7]:
pop.head()
Out[7]:
In [8]:
# 컬럼명 변경

pop.rename(columns = {'동별(2)':'자치구', '구분별(1)':'국적', '구분별(2)':'성별', '데이터':'인구수'}, inplace=True)
In [9]:
crime.head()
Out[9]:
# 필요없는 컬럼 삭제

cctv.drop(columns = ['수정 일시'], inplace=True)
pop.drop(columns = ['시점'], inplace=True)
In [11]:
pop['동별(1)'].unique()
Out[11]:
array(['합계'], dtype=object)
In [12]:
pop.drop(columns = ['동별(1)'], inplace=True)
In [13]:
cctv.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 83734 entries, 0 to 83733
Data columns (total 5 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   자치구      83734 non-null  object 
 1   안심 주소    83734 non-null  object 
 2   위도       83734 non-null  float64
 3   경도       83734 non-null  float64
 4   CCTV 수량  83734 non-null  int64  
dtypes: float64(2), int64(1), object(2)
memory usage: 3.2+ MB
In [14]:
pop.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   국적      100 non-null    object
 1   성별      100 non-null    object
 2   자치구     100 non-null    object
 3   인구수     100 non-null    int64 
dtypes: int64(1), object(3)
memory usage: 3.3+ KB
In [15]:
crime.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 310 entries, 0 to 309
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   구분      310 non-null    object
 1   죄종      310 non-null    object
 2   발생검거    310 non-null    object
 3   건수      310 non-null    int64 
dtypes: int64(1), object(3)
memory usage: 9.8+ KB
In [16]:
crime['구분'].unique()
Out[16]:
array(['중부', '종로', '남대문', '서대문', '혜화', '용산', '성북', '동대문', '마포', '영등포',
       '성동', '동작', '광진', '서부', '강북', '금천', '중랑', '강남', '관악', '강서', '강동',
       '종암', '구로', '서초', '양천', '송파', '노원', '방배', '은평', '도봉', '수서'],
      dtype=object)
In [17]:
crime.rename(columns={'구분':'관서'}, inplace=True)
In [18]:
# crime데이터에 자치구 정보 추가를 위한 경찰서 정보 데이터 불러오기

pol = pd.read_csv('서울경찰서.csv')
In [19]:
pol.head()
Out[19]:
In [20]:
# 관서명 변경
In [21]:
pol['관서'] = pol['관서'].str.replace('서울', '')
pol['관서'] = pol['관서'].str.replace('경찰서', '')

pol

# 자치구 컬럼 생성
In [23]:
pol['자치구'] = pol['주소'].str.split(' ').str[1]
In [24]:
pol.drop(columns = ['주소'], inplace=True)
In [25]:
# crime 데이터와 합치기
In [26]:
crime = pd.merge(crime, pol, on = '관서')
In [27]:
crime
Out[27]:
In [28]:
# pivot하여 데이터 정리
crime.drop(columns = ['관서'], inplace=True)

crime = crime.pivot_table(crime, index=['자치구'],
                          columns=['죄종', '발생검거'],
                          aggfunc=[np.sum])
crime

# Null값 0으로 대치

crime = crime.fillna(0)
crime.isnull().sum()
Out[29]:
         죄종     발생검거
sum  건수  강간     검거      0
                발생      0
         강간,추행  검거      0
                발생      0
         강도     검거      0
                발생      0
         살인     검거      0
                발생      0
         절도     검거      0
                발생      0
         폭력     검거      0
                발생      0
dtype: int64
In [30]:
# sum, 건수 컬럼명 삭제

crime.columns = crime.columns.droplevel([0, 1])
crime.head()
Out[30]:
In [31]:
# 레벨0, 레벨1의 컬럼명을 합쳐 컬럼명 변경

tmp = [
    crime.columns.get_level_values(0)[n] + " "
    + crime.columns.get_level_values(1)[n]
    for n in range(0, len(crime.columns.get_level_values(0)))
]
crime.columns = tmp
crime.head()
Out[31]:
In [32]:
# 검거율 계산

target = ["강간 검거율", "강간,추행 검거율", "강도 검거율", "살인 검거율", "절도 검거율", "폭력 검거율"]
num = ["강간 검거", "강간,추행 검거", "강도 검거", "살인 검거", "절도 검거", "폭력 검거"]
den = ["강간 발생", "강간,추행 발생", "강도 발생", "살인 발생", "절도 발생", "폭력 발생"]

crime[target] = crime[num].div(crime[den].values)
crime.head()
Out[32]:
In [33]:
# 검거 삭제

crime.drop(columns = ["강간 검거", "강간,추행 검거", "강도 검거", "살인 검거", "절도 검거", "폭력 검거"], inplace=True)
In [34]:
# 컬럼명 변경

crime.rename(
    columns={"강간 발생" : "강간", "강간,추행 발생" : "강간,추행", "강도 발생" : "강도", "살인 발생" : "살인", "절도 발생" : "절도", "폭력 발생" : "폭력"},
    inplace=True
)
col = ["강간", "강간,추행", "강도", "살인", "절도", "폭력"]
col2 = ["강간 검거율", "강간,추행 검거율", "강도 검거율", "살인 검거율", "절도 검거율", "폭력 검거율"]

# 사건 발생 수 최소-최대 정규화
crime_norm = (crime[col]-crime[col].min())/(crime[col].max()-crime[col].min())
crime_norm[col2] = crime[col2]
crime_norm.head()
Out[36]:
In [37]:
# 검거율 DF

crime_rate = crime_norm.drop(columns = ["강간", "강간,추행", "강도", "살인", "절도", "폭력"])
In [38]:
import seaborn as sns
import matplotlib.pyplot as plt
import platform

from matplotlib import font_manager, rc
plt.rcParams['axes.unicode_minus'] = False

if platform.system() == 'Darwin':
    rc('font', family='AppleGothic')
elif platform.system() == 'Windows':
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc('font', family=font_name)
else:
    print('Unknown system... sorry~~~~') 


plt.figure(figsize=(10, 8))
sns.heatmap(crime_rate, annot=False, cmap="YlGnBu")
plt.show()

 

# 인구수 데이터 국적, 성별 컬럼 삭제

pop = pop.groupby('자치구').sum()
pop.drop(columns = ["국적", "성별"], inplace=True)
pop
# cctv 데이터와 인구수 데이터 합치기

seoul = pd.merge(cctv, pop, on='자치구')
fp1 = np.polyfit(seoul['인구수'], seoul['CCTV 수량'], 1)

f1 = np.poly1d(fp1)
fx = np.linspace(100000, 700000, 100)

plt.figure(figsize=(14, 10))
plt.scatter(seoul['인구수'], seoul['CCTV 수량'], s=50)
plt.plot(fx, f1(fx), ls='dashed', lw=3, color='g')
plt.xlabel('인구수')
plt.ylabel('CCTV 수량')
for n in range(25):
    plt.text(seoul['인구수'][n], seoul['CCTV 수량'][n], seoul.index[n], fontsize=10)
plt.grid()
plt.show()
  • 인구수가 많을수록 CCTV수량이 많은 것으로 보임
In [48]:
# 상관계수

seoul.corr()
Out[48]:
In [49]:
# 범죄 데이터와 합치기

seoul_crime = pd.merge(seoul, crime_norm, on='자치구')
y1 = seoul_crime["강도 검거율"]
y2 = seoul_crime["강도"]


plt.plot(seoul_crime.index, y1, color = 'red')
plt.plot(seoul_crime.index, y2, color = 'blue')

plt.show()
 

In [52]:
crime_norm.corr()

plt.figure(figsize=(10, 8))
sns.heatmap(crime_norm.corr(), cmap = "RdBu_r", annot=False)
plt.show()
In [54]:
sns.pairplot(seoul_crime, vars=["인구수","CCTV 수량","강도 검거율"], kind="reg", height=3)
plt.show()
 

In [55]:
sns.pairplot(seoul_crime, vars=["인구수","CCTV 수량","살인 검거율"], kind="reg", height=3)
plt.show()
In [56]:
sns.pairplot(seoul_crime, vars=["인구수","CCTV 수량","폭력 검거율"], kind="reg", height=3)
plt.show()
In [57]:
corr = seoul_crime.corr()

plt.figure(figsize=(10, 8))
sns.heatmap(corr, cmap = "RdBu_r", annot=False)
plt.show()

반응형