서울시 범죄 데이터 분석(with pivot table, google Maps)

Variety_·2021년 10월 17일
0

Data Analysis

목록 보기
6/10

Analysis Seoul Crime

데이터 개요 및 읽어오기

  • 데이터과학 이란? 시각화, 딥러닝 등 다양함!
  • 이번엔 가정 혹은 인식을 검증하고 표현하는 도구로써 사용

데이터 : 서울시 관서별 5대 범죄현황의 2016년도 데이터

crime_raw_data = pd.read_csv(
    "./data/02. crime_in_Seoul.csv", thousands=",", encoding="euc-kr")
crime_raw_data.head(3)
  • 숫자값들이 콤마(,)를 사용하고 있어 문자로 인식될 수 있다
  • 천단위 구분(thousands=',')이라고 알려주면 콤마를 제거하고 숫자형으로 읽는다.
crime_raw_data.info()
crime_raw_data['죄종'].unique() 
# output: array(['살인', '강도', '강간', '절도', '폭력', nan], dtype=object)
crime_raw_data[crime_raw_data['죄종'].isnull()]
  • 정보를 살펴보면 인덱스가 65534인데 데이터가 310개 -> nan 때문에 그럼

  • nan제거가 아닌 nan이 아닌 데이터만 가져오자!
crime_raw_data = crime_raw_data[crie_raw_data['죄종'].notnull()]
crime_raw_data.info()
  • 그러나 단순 나열된 데이터는 의미가 없음 -> 원하는 데이터 열로 재배치 해야함

Pandas pivot_table !!!

  • 자신이 원하는 기준으로 다시 정렬해줌(index, columns, values, aggfunc)

  • pd.pivot_table(data, index=['index'], values=['values'], aggfuc= func])

  • values에 함수 적용가능, 디폴트는 평균이니 다른적용하려면 aggfunc 옵션에 적용

아래는 pivot_table만들기를 위해 사용할 DataFrame이다.

# 예시
pd.pivot_table(df, index=['Manager','Rep'], values=['Price'], columns=['Product'],aggfunc=[np.sum], fill_value=0, margins=True)  

  • fill_value : NaN에 대한 처리를 지정
  • margins : 총합row가 추가됨
  • 다중 컬럼에서 특정 컬럼 제거 : Data.columns.droplevel([수준])
crime_station.columns = crime_station.columns.droplevel([0, 1])
crime_station.columns

서울시 범죄 현황 데이터 정리

crime_station = crime_raw_data.pivot_table(index=['구분'],columns=['죄종','발생검거'], aggfunc=[np.sum])
crime_station.head()

그러나 pivot_table 사용시 컬럼이나 인덱스가 멀티로 잡힘

crime_station.columns = crime_station.columns.droplevel([0, 1])

을 통해 sum과 건수를 없애준다.

Multi Index에 대한 접근 : crime_station['sum', '건수', '강도', '검거']이런식

  • 현재 index는 경찰서이름으로 되어있어 구별 이름으로 바꾸고 싶음

Pandas에 잘 맞춰진 반복문용 명령 iterrows()

  • pandas 데이터 프레임은 대부분 2차원
  • 이 때 for문을 사용하면 n번째라는 지정을 반복해서 가독률이 떨어짐
  • Pandas 데이터 프레임으로 반복문을 만들 때 iterrows()라는 옵션을 사용하면 편함
  • 받을 때, 인덱스와 내용으로 나누어 받는 것에 주의

Google Maps를 이용한 데이터 정리

import googlemaps
gmaps_key = 'AIzaSyBJRYXiM1aWW1HsVll88zLRZVYQLSaY4Wg'
gmaps = googlemaps.Client(key=gmaps_key)

  • 구별, 위도, 경도 컬럼 추가
crime_station['구별'] = np.nan
crime_station['lat'] = np.nan
crime_station['lng'] = np.nan
  • iterrows() : idx, rows로 반환함
for idx, ros in crime_station.iterrows():
    station_name = '서울'+str(idx)+'경찰서'
    tmp = gmaps.geocode(station_name, lagauage='ko')
    
    tmp[0].get('formatted_address')
    tmp_gu = tmp[0].get('formatted_address')
    
    lat = tmp[0].get('geometry')['location']['lat']
    lng = tmp[0].get('geometry')['location']['lng']
    
    crime_station.loc[idx, 'lat'] = lat
    crime_station.loc[idx, 'lng'] = lng
    crime_station.loc[idx, '구별'] = tmp_gu.split()[2]
  • 멀티컬럼 정리

  • crime_station.columns.get_level_values(index)로 확인가능

tmp = [crime_station.columns.get_level_values(0)[n] + crime_station.columns.get_level_values(1)[n] for n in range(len(crime_station.columns.get_level_values(0)))]
crime_station.columns = tmp

중간중간 데이터를 파일로 저장해두기 ! 테스트 코드가 긴 경우 중간부터 다시 작업할 수 있음

구별 데이터 생성

crime_anal_gu = pd.pivot_table(crime_anal_station, index='구별', aggfunc=np.sum)
del crime_anal_gu['lat']
del crime_anal_gu['lng']
  • 검거율 데이터 생성(다수의 컬럼을 다수의 컬럼으로 나누기)
target = ['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']
num = ['강간검거', '강도검거', '살인검거', '절도검거', '폭력검거']
den = ['강간발생', '강도발생', '살인발생', '절도발생', '폭력발생']
crime_anal_gu[target] = crime_anal_gu[num].div(crime_anal_gu[den].values) * 100
# denominator,numerator로 분모 분자 뜻함 각각

del crime_anal_gu['강간검거']
del crime_anal_gu['강도검거']
del crime_anal_gu['살인검거']
del crime_anal_gu['절도검거']
del crime_anal_gu['폭력검거']

검거율이 100이 넘는 데이터 -> 작년에 검거했을 수도 있음...
heatmap그래프 그리기 위해 100이 넘는건 강제로 100으로 변환

crime_anal_gu[crime_anal_gu[target] > 100] = 100
crime_anal_gu.rename(
    columns={"강간발생":"강간", "강도발생":"강도","살인발생":"살인","절도발생":"절도","폭력발생":"폭력"},
    inplace=True)

범죄 데이터 정렬을 위한 데이터 정리

  • 범죄의 경중에 따라 발생 건수의 차이가 큼, 따라서 정규화시켜야됨
col = ['살인', '강도', '강간', '절도', '폭력']
crime_anal_norm = crime_anal_gu[col] / crime_anal_gu[col].max()
crime_anal_norm.head()
col2=['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']
crime_anal_norm[col2] = crime_anal_gu[col2]
crime_anal_norm.head
  • 구별 CCTV 자료에서 인구수와 CCTV수를 범죄데이터에 붙임
result_CCTV = pd.read_csv("./data/01. CCTV_result.csv",encoding='utf-8',index_col='구별')
crime_anal_norm[["인구수","CCTV"]] = result_CCTV[["인구수","소계"]]
crime_anal_norm.head()
  • 정규화된 범죄발생 건수 전체의 평균을 구해서 범죄의 대표값으로 사용
col = ['강간', '강도', '살인', '절도', '폭력']
crime_anal_norm['범죄'] = np.mean(crime_anal_norm[col], axis=1)
crime_anal_norm.head()

0개의 댓글