Ch3 서울시 범죄 현황 데이터 분석 01-17 (범죄1-3)

김민지·2023년 3월 29일
0
  1. 강남3구 범죄현황 데이터 개요 및 읽어오기
crime_raw_data = pd.read_csv(
	"../data/02. crime_in_Seoul.csv", thousands=",", encoding="euc-kr"
)
  • 숫자값들이 콤마(,)를 사용하고 있어서 문자로 인식될 수 있음
    -> 천단위 구분(thousands=",")라고 알려주면 콤마를 제거하고 숫자형으로 읽음
crime_raw_data.info()

-> info(): 데이터의 개요 확인하기
RangeIndex가 65534인데, 310개이다.

crime_raw_data["죄종"].unique()

-> 특정 컬럼에서 unique 조사
nan 값이 들어가 있다

crime_raw_data[crime_raw_data["죄종"].isnull()].head()
crime_raw_data = crime_raw_data[crime_raw_data["죄종"].notnull()]

-> "죄종"칼럼이 notnull인 것만 다시 넣어줌

  1. Pandas의 pivot_table
  • index, columns, values, aggfunc
df = pd.read_excel("../data/02. sales-funnel.xlsx") # 엑셀 읽기
df.head()
# Name 컬럼을 인덱스로 설정
df.pivot_table(index="Name")
# 멀티 인덱스 설정
df.pivot_table(index=["Name", "Rep", "Manager"])
df.pivot_table(index=["Manager", "Rep"], values="Price")

-> 표의 값들을 price로 지정

# Price 컬럼 sum 연산 적용
df.pivot_table(index=["Manager", "Rep"], values="Price", aggfunc=np.sum)

-> aggfunc 디폴트값은 mean(평균값). 여기선 sum(총합)으로 지정해줌

# Product를 컬럼으로 지정
df.pivot_table(index=["Manager", "Rep"], values="Price", columns="Product", aggfunc=np.sum)
# Nan 값 설정 : fill_value
df.pivot_table(index=["Manager", "Rep"], values="Price", columns="Product", aggfunc=np.sum, fill_value=0)

-> nan값을 0으로 표시함

# 2개 이상 index, values 설정
df.pivot_table(index=["Manager", "Rep", "Product"], values=["Price", "Quantity"], aggfunc=np.sum, fill_value=0)
# aggfunc 2개 이상 설정
df.pivot_table(
    index=["Manager", "Rep", "Product"],
    values=["Price", "Quantity"],
    aggfunc=[np.sum, np.mean],
    fill_value=0,
    margins=True)  # 총계(All) 추가
  1. 서울시 범죄현황 데이터 정리
crime_station = crime_raw_data.pivot_table(
    crime_raw_data,
    index="구분",
    columns=["죄종", "발생검거"],
    aggfunc=[np.sum])
crime_station.head()
crime_station.columns # MultiIndex
crime_station.columns = crime_station.columns.droplevel([0, 1]) # 다중 컬럼에서 특정 컬럼 제거
crime_station.columns
  1. pip명령과 conda명령
  • pip 명령

    Python의 공식 모듈 관리자
    pip list : 현재 설치된 모듈 리스트 반환
    pip install module_name : 모듈 설치
    pip uninstall module_name : 설치된 모듈 제거

  • conda 명령
    -> pip를 사용하면 conda 환경에서 dependency 관리가 정확하지 않을 수 있음
    아나콘다에서는 가급적 conda 명령으로 모듈을 관리하는 것이 좋음

    conda list : 설치된 모듈 list
    conda install module_name : 모듈 설치
    conda uninstall module_name : 모듈 제거
    conda install -c channel_name module_name : 지정된 배포 채널에서 모듈 설치

-> 그러나 모든 모듈이 conda로 설치되는 것은 아님

  1. google maps api 사용 준비하기
  • 구글맵을 깔고, 이를 활용하여 각각의 경찰서가 속해 있는 구를 알아내기
conda install -c conda-forge googlemaps
import googlemaps
gmaps_key = "AIzaSyAc-8jqf4pKjDW91-dggnio0Sda7IdTZqA"
gmaps = googlemaps.Client(key=gmaps_key)
gmaps.geocode("서울영등포경찰서", language="ko")
  1. Python의 for문
for n in [1, 2, 3, 4]:
    print("Number is", n)
for n in range(0, 10):
    print(n ** 2)
  • 위 코드를 한 줄로 : list comprehension
[n ** 2 for n in range(0, 10)]
  • Pandas에 잘 맞춰진 반복문용 명령 iterrows()

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

  1. google maps에서 구별 정보를 얻어 데이터 정리
tmp[0].get("formatted_address").split()[2] # split()은 띄어쓰기 기준으로 문자열을 잘라서 리스트에 넣음
crime_station["구별"] = np.nan
crime_station["lat"] = np.nan
crime_station["lng"] = np.nan

-> 일단 새로운 칼럼을 만들고 NaN으로 채워줌

  • 경찰서 이름에서 소속된 구이름 얻기
  • 구이름과 위도, 경도 정보를 저장할 준비
  • 반복문을 이용해서 위 표의 NaN값을 모두 채워주기
  • iterrows()
count = 0
for idx, rows in crime_station.iterrows():
    station_name = "서울" + str(idx) + "경찰서"
    tmp = gmaps.geocode(station_name, language="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]  # split한 리스트 중 2인덱스를 가져옴
    
    print(count)     # 정상적으로 for문이 돌았는지 확인하기 위함
    count = count + 1
tmp = [
    crime_station.columns.get_level_values(0)[n] + crime_station.columns.get_level_values(1)[n]
    for n in range(0, len(crime_station.columns.get_level_values(0)))    
]
tmp
crime_station.columns = tmp

-> '강도발생','강도검거'등의 이름으로 바꿔줌

# 데이터 저장
crime_station.to_csv("../data/02. crime_in_Seoul_raw.csv", sep=",", encoding="utf-8")
  1. 구별 데이터로 변경하기
crime_anal_station = pd.read_csv("../data/02. crime_in_Seoul_raw.csv", index_col=0, encoding="utf-8") # index_col : "구분"을 인덱스 칼럼으로 설정
crime_anal_gu = pd.pivot_table(crime_anal_station, index="구별", aggfunc=np.sum)

del crime_anal_gu["lat"]
crime_anal_gu.drop("lng", axis=1, inplace=True)
# 검거율 생성
# 하나의 컬럼을 다른 컬럼으로 나누기

crime_anal_gu["강도검거"] / crime_anal_gu["강도발생"]
# 다수의 컬럼을 다른 컬럼으로 나누기
crime_anal_gu[["강도검거", "살인검거"]].div(crime_anal_gu["강도발생"], axis=0).head(3)
# 다수의 컬럼을 다수의 컬럼으로 각각 나누기

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

crime_anal_gu[num].div(crime_anal_gu[den].values).head()
target = ["강간검거율", "강도검거율", "살인검거율", "절도검거율", "폭력검거율"]

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

crime_anal_gu[target] = crime_anal_gu[num].div(crime_anal_gu[den].values) * 100
# 필요없는 칼럼 제거

del crime_anal_gu["강간검거"]
del crime_anal_gu["강도검거"]
crime_anal_gu.drop(["살인검거", "절도검거", "폭력검거"], axis=1, inplace=True)
# 100보다 큰 숫자 찾아서 바꾸기. 검거율이 100 넘기 않도록 하기위함

crime_anal_gu[crime_anal_gu[target] > 100] = 100
# 칼럼 이름 변경

crime_anal_gu.rename(columns={"강간발생":"강간", "강도발생":"강도", "살인발생":"살인", "절도발생":"절도", "폭력발생":"폭력"}, inplace=True)
  1. 서울시 범죄현황 데이터 최종 정리
  • 구별 데이터에서 발생건수 정규화 데이터 생성하기
    -> 본래의 DataFrame은 두고, 정규화된 데이터 따로 만들기
# 정규화 : 최고값은 1, 최솟값은 0
crime_anal_gu["강도"] / crime_anal_gu["강도"].max()
col = ["강간", "강도", "살인", "절도", "폭력"]
crime_anal_norm = crime_anal_gu[col] / crime_anal_gu[col].max()
# 검거율 추가
col2 = ["강간검거율", "강도검거율", "살인검거율", "절도검거율", "폭력검거율"]
crime_anal_norm[col2] = crime_anal_gu[col2]
# 구별 CCTV 자료에서 인구수와 CCTV수 추가

result_CCTV = pd.read_csv("../data/01. CCTV_result.csv", index_col="구별", encoding="utf-8")
crime_anal_norm[["인구수", "CCTV"]] = result_CCTV[["인구수", "소계"]]
# 정규화된 범죄발생 건수 전체의 평균을 구해서 범죄 컬럼 대표값으로 사용

col = ["강간", "강도", "살인", "절도", "폭력"]
crime_anal_norm["범죄"] = np.mean(crime_anal_norm[col], axis=1)
  • np.mean()
np.mean(np.array([1.000000, 1.000000, 0.357143, 0.977118, 0.733773]))

-> 평균을 구함

np.mean(np.array([[1.000000, 1.000000, 0.357143, 0.977118, 0.733773],
         [0.310078, 0.358974, 0.285714, 0.477799, 0.463880]]
        ), axis=1  # axis=1은 행, axis=0은 열 기준으로 계산함
       )

-> array([0.8136068, 0.379289 ])

np.mean(np.array([[1.000000, 1.000000, 0.357143, 0.977118, 0.733773],
         [0.310078, 0.358974, 0.285714, 0.477799, 0.463880]]
        ), axis=0  # axis=1은 행, axis=0은 열 기준으로 계산함
       )

-> array([0.655039 , 0.679487 , 0.3214285, 0.7274585, 0.5988265])

# 검거율의 평균을 구해서 검거 컬럼의 대표값으로 사용

col = ["강간검거율", "강도검거율", "살인검거율", "절도검거율", "폭력검거율"]
crime_anal_norm["검거"] = np.mean(crime_anal_norm[col], axis=1)

<제로베이스 데이터 취업 스쿨>

0개의 댓글