비트교육센터/파이썬

[비트교육센터] 자바 기반 풀스택 개발자 양성 과정(Bigdata) 7일차

달의요정루나 2023. 6. 9. 20:35

1. Seoul_CCTV

- 서울의 CCTV데이터로 데이터 분석을 하려고 한다.

 

1) 코딩문

[1]

- source폴더에 새로운 폴더 practice를 선언한다.

- 그리고 그안에 data폴더를 선언한다.

[2]

- data폴더에 파일 2개를 넣는다.

population.txt
0.00MB
서울시 CCTV 설치운영 현황(자치구)-연도별.csv
0.00MB

2) 코딩문

[1]

import numpy as np
import pandas as pd
cctv_seoul = pd.read_csv('data/서울시 CCTV 설치운영 현황(자치구)-연도별.csv',
                        header=1,thousands=',',encoding='cp949')#첫줄은 날리고 시작함
cctv_seoul.head() #만약 파일이 안뜨면 해당 ipynb을 죽였다 띄여야 한다.

- csv파일을 첫번째 열을 먼저 날리고 시작한다. header는 열 이름으로 사용할 행을 지정한다. header=1을 지정해 원본데이터에서 첫줄을 무시하고 읽으라고 한다.

- thousands=',' 는 천 단위 자리수 구분으로 콤마를 없애고 불러오는 것이다.

- encoding='cp949'은 한글 인코딩의 한 종류로 EUC-KR의 확장형이다.

 

--> 결과

[2]

cctv_seoul.drop([0],inplace=True)#인덱스0을 날렸다.
cctv_seoul.head()

- 출력한 표에서 행의 인덱스0을 날리고 표를 출력한다.

- inplace=True는 기존 데이터에 변경된 설정으로 덮어쓴다는 것을 의미한다.

--> 결과

[3]

cctv_seoul.info()

- info(): 데이터에 대한 전반적인 정보를 나타낸다.

--> 결과

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 25 entries, 1 to 25
Data columns (total 13 columns):
 #   Column    Non-Null Count  Dtype 
---  ------    --------------  ----- 
 0   구분        25 non-null     object
 1   총계        25 non-null     int64 
 2   2011년 이전  25 non-null     int64 
 3   2011년     25 non-null     int64 
 4   2012년     25 non-null     int64 
 5   2013년     25 non-null     int64 
 6   2014년     25 non-null     int64 
 7   2015년     25 non-null     int64 
 8   2016년     25 non-null     int64 
 9   2017년     25 non-null     int64 
 10  2018년     25 non-null     int64 
 11  2019년     25 non-null     int64 
 12  2020년     25 non-null     int64 
dtypes: int64(12), object(1)
memory usage: 2.7+ KB

[4]

cctv_seoul.head()

- 불러온 데이터의 상위 5개의 행을 출력한다.

--> 결과

[5]

cctv_seoul.rename(columns={cctv_seoul.columns[0]:'구별'},inplace=True)
cctv_seoul.head()

- 컬럼명을 바꾼다.

- rename(columns={'기존이름' : '바꿀이름'}, inplace=True) 구성으로 컬럼 0번 인덱스에 있는 이름을 '구별'로 바꾸어준다.

--> 결과

3) 코딩문

[1]

pop_seoul=pd.read_csv('data/population.txt',header=2,delim_whitespace=True,
                     thousands=',')
pop_seoul.head()

- header=2 : 데이터의 3번째 행부터 출력한다.

- delim_whitespace=True : 공백으로 구분된 파일을 읽을 때 사용한다.

- thousands=',' : 천 단위 자리수 구분으로 콤마를 없애고 불러온다.

--> 결과

[2]

pop_seoul.drop(['기간','세대','남자','여자','남자.1','여자.1',
               '남자.2','여자.2','세대당인구'],axis=1,inplace=True)
pop_seoul.head()

- drop함수는 데이터에서 열을 삭제하는 메소드이다.

- axis=1: 판다스에서 컬럼을 삭제한다.

- [ ]안에는 삭제한 컬럼명을 정해준다.

--> 결과

[3]

pop_seoul.rename(columns={pop_seoul.columns[0]:'구별',pop_seoul.columns[1]:'인구수',
                          pop_seoul.columns[2]:'한국인',
                          pop_seoul.columns[3]:'외국인',
                          pop_seoul.columns[4]:'고령자'},inplace=True)
pop_seoul.head()

- rename함수: 컬럼의 이름을 바꿀때 이용된다.

- 인덱스로 선언해서 각각 무슨 이름으로 바꿀지 정한다.

--> 결과

[4]

pop_seoul.drop([0],inplace=True)
pop_seoul.head()

- 인덱스 0번인 행을 삭제한다.

- axis=0은 default값이다.

--> 결과

4) 코딩문

[1]

cctv_seoul['구별'].unique()

- unique(): 데이터의 고유값들이 어떤 종류들인지 알고 싶을때 사용한다.

- 컬럼 '구별'에 대한 고유값들을 알아본다.

--> 결과

array(['종로구', '중 구', '용산구', '성동구', '광진구', '동대문구', '중랑구', '성북구', '강북구',
       '도봉구', '노원구', '은평구', '서대문구', '마포구', '양천구', '강서구', '구로구', '금천구',
       '영등포구', '동작구', '관악구', '서초구', '강남구', '송파구', '강동구'], dtype=object)

[2]

pop_seoul['구별'].unique()

--> 결과

array(['종로구', '중구', '용산구', '성동구', '광진구', '동대문구', '중랑구', '성북구', '강북구',
       '도봉구', '노원구', '은평구', '서대문구', '마포구', '양천구', '강서구', '구로구', '금천구',
       '영등포구', '동작구', '관악구', '서초구', '강남구', '송파구', '강동구'], dtype=object)

[3]

cctv_seoul.loc[cctv_seoul['구별']=='중 구','구별']='중구'
cctv_seoul['구별'].unique()

- loc[행의 인덱싱 값, 열 값]: 행의 인덱싱 값은 컬럼의 '구별'에서 '중 구'의 값을 가진 값이다. 즉, 인덱싱 값은 2이다. 그리고 열 값인 '구별'에 위치한 값을 '중구'로 바꾸어 준다.

--> 결과

array(['종로구', '중구', '용산구', '성동구', '광진구', '동대문구', '중랑구', '성북구', '강북구',
       '도봉구', '노원구', '은평구', '서대문구', '마포구', '양천구', '강서구', '구로구', '금천구',
       '영등포구', '동작구', '관악구', '서초구', '강남구', '송파구', '강동구'], dtype=object)

[4]

cctv_seoul.info() #인덱스 25개

--> 결과

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 25 entries, 1 to 25
Data columns (total 13 columns):
 #   Column    Non-Null Count  Dtype 
---  ------    --------------  ----- 
 0   구별        25 non-null     object
 1   총계        25 non-null     int64 
 2   2011년 이전  25 non-null     int64 
 3   2011년     25 non-null     int64 
 4   2012년     25 non-null     int64 
 5   2013년     25 non-null     int64 
 6   2014년     25 non-null     int64 
 7   2015년     25 non-null     int64 
 8   2016년     25 non-null     int64 
 9   2017년     25 non-null     int64 
 10  2018년     25 non-null     int64 
 11  2019년     25 non-null     int64 
 12  2020년     25 non-null     int64 
dtypes: int64(12), object(1)
memory usage: 2.7+ KB

[5]

pop_seoul.info() #인덱스 25개

--> 결과

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 25 entries, 1 to 25
Data columns (total 5 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   구별      25 non-null     object
 1   인구수     25 non-null     int64 
 2   한국인     25 non-null     int64 
 3   외국인     25 non-null     int64 
 4   고령자     25 non-null     int64 
dtypes: int64(4), object(1)
memory usage: 1.1+ KB

[6]

cctv_seoul.sort_values(by='총계',ascending=True)

- sort_values메소드는 값을 기준으로 레이블을 정렬하는 메소드이다.

- by='총계': 총계를 기준 정렬한다.

- ascending=True: 오름차순으로 정렬한다.(False는 내림차순)

--> 결과

[7]

cctv_seoul.sort_values(by='총계',ascending=False)

- 총계를 기준으로 내림차순 정렬한다.

--> 결과

[8]

cctv_seoul['최근증가율']=(cctv_seoul['2016년']+cctv_seoul['2017년']
                    +cctv_seoul['2018년']+cctv_seoul['2019년']
                    +cctv_seoul['2020년'])/(cctv_seoul['2011년 이전']
                    +cctv_seoul['2011년']+cctv_seoul['2012년']
                    +cctv_seoul['2013년']+cctv_seoul['2014년']
                    +cctv_seoul['2015년'])*100
cctv_seoul.sort_values(by='최근증가율',ascending=False)

- 최근증가율 칼럼을 추가한다.

- 2011년이전에서 2015년까지의 값을 더한후 2016에서 2020년까지 더한 값을 나누어 준다.

- 최근 증가율을 기준으로 내림차순으로 정렬한다.

--> 결과

5) 코딩문

[1]

pop_seoul.head()

- pop_seoul의 상위 5개 행을 출력한다.

--> 결과

[2]

pop_seoul['외국인 비율']=pop_seoul['외국인']/pop_seoul['인구수']*100
pop_seoul['고령자 비율']=pop_seoul['고령자']/pop_seoul['인구수']*100
pop_seoul.head()

- 외국인 비율, 고령자 비율 컬럼을 추가하고 해당 비율을 구한다.

--> 결과

[3]

pop_seoul.sort_values(by='인구수',ascending=False)

--> 결과

[4]

pop_seoul.sort_values(by='외국인',ascending=False)

--> 결과

[5]

pop_seoul.sort_values(by='외국인 비율',ascending=False)

--> 결과

[6]

pop_seoul.sort_values(by='고령자',ascending=False)

--> 결과

[7]

pop_seoul.sort_values(by='고령자 비율',ascending=False)

--> 결과

6) 코딩문

[1]

data_result=pd.merge(cctv_seoul, pop_seoul, on='구별')
data_result.head()

- merge: 두 객체를 병합하는 메소드이다.

- cctv_seoul과 pop_seoul을 '구별'기준으로 병합한다.

--> 결과

[2]

data_result.drop(['2011년 이전', '2011년', '2012년', '2013년', '2014년', '2015년', '2016년', \
                  '2017년', '2018년', '2019년', '2020년'], axis=1, inplace=True)
data_result.head()

- data_result에서 버릴 칼럼을 정한다.

- axis=1: 열방향으로 삭제한다.

--> 결과

[3]

data_result.set_index('구별',inplace=True)
data_result.head()

- set_index: 컬럼명(열)을 인덱스로 사용할수 있게 해주는 메소드이다.

--> 결과

[4]

data_result.to_csv('data/cctv_pop_seoul.csv',sep=',',encoding='utf-8')

- data_result를 csv파일로 만들어준다.

- sep=',': csv파일의 구분자를 설정한다.

--> 결과

[5]

np.corrcoef(data_result['고령자 비율'],data_result['총계'])

- corrcoef(): 피어슨 상관계수 값을 계산해준다.

--> 결과

array([[ 1.        , -0.42943277],
       [-0.42943277,  1.        ]])

[6]

np.corrcoef(data_result['외국인 비율'],data_result['총계'])

--> 결과

array([[ 1.       , -0.1694645],
       [-0.1694645,  1.       ]])

[7]

np.corrcoef(data_result['인구수'],data_result['총계'])

--> 결과

array([[1.        , 0.45645369],
       [0.45645369, 1.        ]])

7) 코딩문

[1]

- seaborn 라이브러리를 설치해준다.

import seaborn as sns
import matplotlib.pyplot as plt

- seaborn 라이브러리를 import한다.

- seaborn

1) 파이썬 데이터 시각화 라이브러리이다.

2) matplotlib 대비 손쉽게 그래프를 그리고 그래프 스타일 설정을 할 수 있다는 장점이 있다.

[2]

import platform
from matplotlib import font_manager, rc # Runtime Configuration

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

- 운영체제에 따른 글꼴설정 if문이다.

sns.pairplot(data_result, x_vars=['고령자 비율','외국인 비율','인구수'],
            y_vars=['총계'],kind='reg',height=3)
plt.show()

- pairplot: 데이터에 들어 있는 각 컬럼(열)들의 모든 상관 관계를 출력한다.

- x_vars와 y_vars: 각각 x와 y에 어떤 값을 배치할지 설정한다.

- kind='reg': 어떤 종류의 그래프를 출력할지 설정한다.(reg는 일반그래프)

- height: 인치당 눈금 몇 개 설정할 지 설정한다.

--> 결과

[3]

data_result.sort_values(by='총계',ascending=False)

--> 결과

[4]

data_result['총계'].plot(kind='barh',grid=True,figsize=(10,10))
plt.show()

- kind: 플로팅할 유형을 선택한다. (barh: 세로그래프)

- grid: 격자를 설정

- figsize: 출력할 fig의 크기입니다.

--> 결과

[5]

data_result['총계'].sort_values().plot(kind='barh',grid=True,figsize=(10,10))
plt.show()

- sort_values()를 붙여 크기별로 그래프를 정렬해준다.

--> 결과

[6]

plt.scatter(data_result['인구수'],data_result['총계'],s=50)
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.show()

- Scatter plot(산점도)은 두 변수의 상관 관계를 직교 좌표계의 평면에 점으로 표현하는 그래프이다.

- 인구수, 총계값에 해당하는 위치에 기본 마커가 표시된다.

- s는 크기로 마커의 크기를 설정한다.

--> 결과

[7]

fp=np.polyfit(data_result['인구수'],data_result['총계'],1)
fp

- polyfit함수는 주어진 데이터에 대해 최소 제곱을 갖는 다항식 피팅을 반환합니다.

- 차수+1(함수에서 1이 차수이다.)만큼의 숫자 배열이 반환된다.

--> 결과

array([4.03056886e-03, 1.43272762e+03])

---

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

- poly1d는 다항식 생성 함수로 입력배열을 항으로 간주해 다항식을 생성한다.

- linspace: 1차원 배열 만들기, 그래프 그리기에서 수평축의 간격 만들기 등에 사용된다.

---

plt.scatter(data_result['인구수'],data_result['총계'],s=50)
plt.plot(fx,f1(fx),ls='dashed',color='g')
plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.grid()
plt.show()

- plot함수에서 ls는 그래프 모양을 설정할 수 있다.

- plot함수는 분포도에서 평균값을 구한 막대그래프이다.

--> 결과

[8]

data_result['오차']=np.abs(data_result['총계']-f1(data_result['인구수']))
df_sort = data_result.sort_values(by='오차',ascending=False)
df_sort.head()

- data_result에 오차 컬럼을 생성해 준다.

--> 결과

[9]

plt.figure(figsize=(14,10))
plt.scatter(data_result['인구수'],data_result['총계'],s=50,c=data_result['오차'])
plt.plot(fx,f1(fx),ls='dashed',color='g')

for n in range(10):
    plt.text(df_sort['인구수'][n]*1.02,df_sort['총계'][n]*0.98,
            df_sort.index[n],fontsize=15)

plt.xlabel('인구수')
plt.ylabel('CCTV')
plt.colorbar()
plt.grid()
plt.show()

- 인구수, 총계에 따라 산점도에 지역구 텍스트를 삽입한다.

--> 결과

8) 코딩문

[1]

- conda install folium을 실행해 folium라이브러리를 설치한다.

- folium: 지도를 그랴주는 Python 모듈이다.

https://python-visualization.github.io/folium/quickstart.html#Markers

 

Quickstart — Folium 0.14.0 documentation

Polylines folium can show linear elements on a map using PolyLine. This object can help put emphasis on a trail, a road, or a coastline. m = folium.Map(location=[-71.38, -73.9], zoom_start=11) trail_coordinates = [ (-71.351871840295871, -73.655963711222626

python-visualization.github.io

import folium
import json

- json은 데이터를 문자열의 형태로 나타내기 위해 사용되는 언어이다.

- folium과 json을 import한다.

seoul_geo.json
0.01MB

- 해당 파일은 서울 지역구에 대한 위치와 정보를 담은 json파일이다.

- 해당파일은 practive/data경로에 집어넣는다.

[2]

geo_path='data/seoul_geo.json'
geo_str=json.load(open(geo_path,encoding='utf-8'))

- json파일을 실행한다.

map = folium.Map(location=[37.5502, 126.982],zoom_start=11)
#Map함수에 지정할 위도와 경도를 location값으로 입력한다.

folium.Choropleth(
    geo_data=geo_str,#경계선 좌표값이 담긴 데이터(json파일에 있다.)
    data = data_result['cctv비율'],#cctv비율에 대한 데이터를 넣는다.
    columns=[data_result.index, data_result['cctv비율']],#어떤 컬럼값을 넣을지 결정한다.
    fill_color='PuRd',#밀집도에 따른 색상의 변화이다. 보라색에서 붉은색으로 간다.
    key_on='feature.id'#어떤 칼럼이 feature하고 매칭되는지 인식
).add_to(map)
map

- fill_color관련 사이트

https://matplotlib.org/stable/tutorials/colors/colormaps.html

 

Choosing Colormaps in Matplotlib — Matplotlib 3.7.1 documentation

Note Click here to download the full example code Choosing Colormaps in Matplotlib Matplotlib has a number of built-in colormaps accessible via matplotlib.colormaps. There are also external libraries that have many extra colormaps, which can be viewed in t

matplotlib.org

--> 결과

 

2. Police

- 각 경찰서마다 수사한 범죄건수에 관련된 데이터 분석이다.

 

1) 코딩문

[1]

import pandas as pd
import numpy as np

police_2000_2020.csv
0.01MB

- police_2000_2020.csv를 다운받아서 data폴더 안에 넣어준다.

[2]

crime_police=pd.read_csv('data/police_2000_2020.csv',encoding='cp949')
crime_police.head(10)

- 해당 csv파일을 읽어온다. euc-kr타입이기 때문에 인코딩이 필수이다.

-->결과

[3]

crime_police.set_index(['구분','죄종','발생검거'],inplace=True)
crime_police.head(10)

- set_index함수로 열 3개의 멀티인덱스를 지정한다.

--> 결과

[4]

crime_police=crime_police.unstack(-1)
crime_police.head(10)

- unstack을 선언해 행을 언피벗해 하위 열로 변환하는 메소드이다.

- level: 멀티인덱스일 경우 하위열로 변환할 행의 레벨이다. 디폴트값은 -1이다.

--> 결과

[5]

crime_police=crime_police.unstack(-1)
crime_police.head(10)

--> 결과

[6]

crime_police=crime_police.droplevel(0,axis=1) #컬럼의 첫번째 레벨을 드롭시킴
crime_police.head(10) #컬럼 맨 윗단이 사라졌다.

--> 결과

[7]

col_dict1 = ['검거nan','강간검거', '강도검거', '살인검거', '절도검거', '폭력검거']
col_dict2 = ['발생nan','강간발생', '강도발생', '살인발생', '절도발생', '폭력발생']
#새로운 컬럼이름을 미리정함
c1 = crime_police['검거'].rename(
    columns={crime_police['검거'].columns[i]:j for i, j in enumerate(col_dict1)})
c2 = crime_police['발생'].rename(
    columns={crime_police['발생'].columns[i]:j for i, j in enumerate(col_dict2)})
#기존은 컬럼이 무려 2레벨이어서 rename을 이용해 검거에 관련된 컬럼과 발생에 관련된 컬럼들을
# col_dict1, col_dict2로 순서대로 변경해준다.
crime_police = pd.merge(c1, c2, on='구분')
crime_police.head()

--> 결과

[8]

crime_police.drop(['검거nan', '발생nan'], axis=1, inplace=True)
crime_police.head(10)

- 컬럼 검서nan, 발생nan을 열단위로 삭제한다.

--> 결과

 

2) 코딩문

[1]

- 터미널에서 conda install googlemap을 입력해서 라이브러리를 다운받는다.

- 그러나 조회하려는 googlemaps 패키지가 없어서 다운로드가 안된다.

 

https://anaconda.org/conda-forge/googlemaps

 

Googlemaps :: Anaconda.org

Description Use Python? Want to geocode something? Looking for directions? Maybe matrices of directions? This library brings the Google Maps API Web Services to your Python application. Analytics

anaconda.org

- 아니콘다 사이트에서 Googlemaps 관련 installers코드를 조회한다.

- conda install -c conda-forge googlemaps를 입력해서 googlemaps 라이브러리를 다운받는다.

 

[2]

import googlemaps

- Google Maps Geolocation API: 구글 서비스의 이용자뿐 아니라 누구나 사용이 가능한 위치기반 서비스이다. WPS 위치 측위 방법을 지원하는 서비스로, 사용자가 확인 가능한 Wi-FI AP과 기지국의 정보를 기반으로 위치 정보를 제공한다.

(여담으로 API값은 다른분께 빌렸다.)

 

gmaps_key=''#받은 API값을 넣는다. 절대 아무에게나 공게하면 안된다.
gmaps = googlemaps.Client(key=gmaps_key)
gmaps.geocode('서울중부경찰서',language='ko') #조회하는 언어가 한국어하는거 명시

- 한국어 설정으로 서울중부경찰서의 결과값을 받아온다.

--> 결과

[{'address_components': [{'long_name': '27',
    'short_name': '27',
    'types': ['premise']},
   {'long_name': '수표로',
    'short_name': '수표로',
    'types': ['political', 'sublocality', 'sublocality_level_4']},
   {'long_name': '중구',
    'short_name': '중구',
    'types': ['political', 'sublocality', 'sublocality_level_1']},
   {'long_name': '서울특별시',
    'short_name': '서울특별시',
    'types': ['administrative_area_level_1', 'political']},
   {'long_name': '대한민국',
    'short_name': 'KR',
    'types': ['country', 'political']},
   {'long_name': '100-032',
    'short_name': '100-032',
    'types': ['postal_code']}],
  'formatted_address': '대한민국 서울특별시 중구 수표로 27',
  'geometry': {'location': {'lat': 37.56361709999999, 'lng': 126.9896517},
   'location_type': 'ROOFTOP',
   'viewport': {'northeast': {'lat': 37.5649660802915,
     'lng': 126.9910006802915},
    'southwest': {'lat': 37.5622681197085, 'lng': 126.9883027197085}}},
  'partial_match': True,
  'place_id': 'ChIJc-9q5uSifDURLhQmr5wkXmc',
  'plus_code': {'compound_code': 'HX7Q+CV 대한민국 서울특별시',
   'global_code': '8Q98HX7Q+CV'},
  'types': ['establishment', 'point_of_interest']}]

- 여기에서 formatted_address와 geometry를 이용할 것이다.

 

[3]

station_name=[]
for name in crime_police.index:
    station_name.append('서울'+str(name)+'경찰서')
    
station_name

- crime_police에서 인덱스 값을 가져와 station_name 리스트를 만든다.

--> 결과

['서울강남경찰서',
 '서울강동경찰서',
 '서울강북경찰서',
 '서울강서경찰서',
 '서울관악경찰서',
 '서울광진경찰서',
 '서울구로경찰서',
 '서울금천경찰서',
 '서울남대문경찰서',
 '서울노원경찰서',
 '서울도봉경찰서',
 '서울동대문경찰서',
 '서울동작경찰서',
 '서울마포경찰서',
 '서울방배경찰서',
 '서울서대문경찰서',
 '서울서부경찰서',
 '서울서초경찰서',
 '서울성동경찰서',
 '서울성북경찰서',
 '서울송파경찰서',
 '서울수서경찰서',
 '서울양천경찰서',
 '서울영등포경찰서',
 '서울용산경찰서',
 '서울은평경찰서',
 '서울종로경찰서',
 '서울종암경찰서',
 '서울중랑경찰서',
 '서울중부경찰서',
 '서울혜화경찰서']

---

print(len(station_name))

- 리스트 길이를 알아본다.

--> 결과

31

 

3) 코딩문

[1]

- tqdm 라이브러리를 설치한다.(conda install tqdm)

- tqdm: for 루프와 같은 반복문에서 사용하여 현재 상태를 시각화하고, 진행률을 나타내며, 소요 시간 등을 보여준다.

from tqdm.notebook import tqdm
station_address=[]#주소
station_lat=[]#위도
station_lng=[]#경도

for name in tqdm(station_name):
    
    tmp=gmaps.geocode(name,language='ko')
    # 'name'의 구글 geocode 를 가져옴. 이 때 name 은 station_name 으로 찾는다. 언어는 한국어
   
   station_address.append(tmp[0].get('formatted_address'))
    # dictionary 형태 이기에 keys값(formatted_address)으로 values 값을 가져온다
    
    station_lat.append(tmp[0].get('geometry')['location']['lat'])
    #리스트에서 위도를 추출
   	#keys값 : ('geometry')['location']['lat']
   
   station_lng.append(tmp[0].get('geometry')['location']['lng'])
   #리스트에서 경도를 추출
   # keys값 : ('geometry')['location']['lng']
   
    print(name + ': '+ tmp[0].get('formatted_address'))
    # 마지막 출력은 formatted_address(keys값)의  values
    #각 list (station_address, station_lat, station_lng) 에는 주소, 위도, 경도 모두 저장되어있는 상태

--> 결과

100%
 
31/31 [00:03<00:00, 9.54it/s]
서울강남경찰서: 대한민국 서울특별시 강남구 테헤란로114길 11
서울강동경찰서: 대한민국 서울특별시 강동구 성내로 57
서울강북경찰서: 대한민국 서울특별시 강북구 오패산로 406
서울강서경찰서: 대한민국 서울특별시 양천구 신월동 화곡로 73
서울관악경찰서: 대한민국 서울특별시 관악구 관악로5길 33
서울광진경찰서: 대한민국 서울특별시 광진구 구의동 자양로 167
서울구로경찰서: 대한민국 서울특별시 구로구 새말로 97 신도림테크노마트 5층
서울금천경찰서: 대한민국 서울특별시 금천구 시흥대로73길 50
서울남대문경찰서: 대한민국 서울특별시 중구 한강대로 410
서울노원경찰서: 대한민국 서울특별시 노원구 노원로 283
서울도봉경찰서: 대한민국 서울특별시 도봉구 노해로 403
서울동대문경찰서: 대한민국 서울특별시 동대문구 약령시로21길 29
서울동작경찰서: 대한민국 서울특별시 동작구 노량진로 148
서울마포경찰서: 대한민국 서울특별시 마포구 마포대로 183
서울방배경찰서: 대한민국 서울특별시 서초구 동작대로 204
서울서대문경찰서: 대한민국 서울특별시 서대문구 통일로 113
서울서부경찰서: 대한민국 서울특별시 은평구 진흥로 58
서울서초경찰서: 대한민국 서울특별시 서초구 서초3동 반포대로 179
서울성동경찰서: 대한민국 서울특별시 성동구 행당동 왕십리광장로 9
서울성북경찰서: 대한민국 서울특별시 성북구 삼선동 보문로 170
서울송파경찰서: 대한민국 서울특별시 송파구 중대로 221
서울수서경찰서: 대한민국 서울특별시 강남구 개포로 617
서울양천경찰서: 대한민국 서울특별시 양천구 목동동로 99
서울영등포경찰서: 대한민국 서울특별시 영등포구 국회대로 608
서울용산경찰서: 대한민국 서울특별시 용산구 백범로 329
서울은평경찰서: 대한민국 서울특별시 은평구 연서로 365
서울종로경찰서: 대한민국 서울특별시 종로구 인사동5길 41
서울종암경찰서: 대한민국 서울특별시 종암경찰서
서울중랑경찰서: 대한민국 서울특별시 중랑구 묵제2동 249-2
서울중부경찰서: 대한민국 서울특별시 중구 수표로 27
서울혜화경찰서: 대한민국 서울특별시 종로구 창경궁로 112-16

[2]

print(len(station_address),len(station_lat),len(station_lng))

- 주소, 위도, 경도 리스트의 길이를 출력한다.

--> 결과

31 31 31

[3]

print(station_lat[:10])

--> 결과

[37.5094352, 37.528511, 37.63719740000001, 37.5397827, 37.4743945, 37.5428231, 37.5074418, 37.4568129, 37.5547584, 37.6421389]

---

print(station_lng[:10])

--> 결과

[127.0669578, 127.1268224, 127.0273048, 126.8299968, 126.9513489, 127.0838395, 126.8902237, 126.8968061, 126.9734981, 127.0710473]

[4]

crime_police.head()

--> 결과

[5]

gu_name=[]
for name in station_address:
    tmp = name.split()
    tmp_gu = [gu for gu in tmp if gu[-1] == '구'][0]
    #조회한 주소들을 띄어쓰기로 나누었을때
    #단어 끝에 '구'가 있는 것들은 전부 추출
    gu_name.append(tmp_gu)

crime_police['구별']=gu_name
crime_police.head()

--> 결과

---

test=['대한민국','서울특별시','관악구','나머지주소']
print([gu for gu in test if gu[-1] == '구'][0])

- 해당처럼 구에 관련된 글자를 추출한다.

--> 결과

관악구

 

[6]

crime_police.reset_index(drop=False, inplace=True)
crime_police

- reset_index: 설정 인덱스를 제거하고 기본 인덱스(0,1,2, ... , n)으로 변경하는 메서드dlek.

- drop: 제거한 인덱스를 열에 추가할지 여부이다. 기본값은 False로 제거된 인덱스는 열로 반환된다.

- inplace: pandas공통 인수로, 원본을 변경할지 여부이다.

--> 결과

[7]

crime_police.loc[crime_police['구분']=='도봉','강간검거']=87
crime_police

- NaN값인 도봉구의 '강간검거'값을 87로 변경해준다.

--> 결과

[8]

crime_police.loc[crime_police['구분']=='도봉','강간발생']=82
crime_police.loc[crime_police['구분']=='방배','강간검거']=50
crime_police.loc[crime_police['구분']=='방배','강간발생']=63
crime_police.loc[crime_police['구분']=='성북','강간검거']=77
crime_police.loc[crime_police['구분']=='성북','강간발생']=95
crime_police.loc[crime_police['구분']=='양천','강간검거']=90
crime_police.loc[crime_police['구분']=='양천','강간발생']=109
crime_police.loc[crime_police['구분']=='종암','강간검거']=44
crime_police.loc[crime_police['구분']=='종암','강간발생']=47
crime_police

- 다른 Nan값도 전부 채워준다.

 

[9]

crime_anal=pd.pivot_table(crime_police, index='구별',aggfunc=np.sum)
crime_anal

- pivot table: 데이터 열 중에서 두 개의 열을 각각 행 인덱스, 열 인덱스로 사용하여 데이터를 조회하여 펼쳐놓은 것을 말한다.

- index: 인덱스를 정한다.

- aggfunc: 산식을 설정한다. 평균값이 아닌 합계로 설정했다.

--> 결과

[10]

crime_anal['강간검거율'] = crime_anal['강간검거']/crime_anal['강간발생']*100
crime_anal['강도검거율'] = crime_anal['강도검거']/crime_anal['강도발생']*100
crime_anal['살인검거율'] = crime_anal['살인검거']/crime_anal['살인발생']*100
crime_anal['절도검거율'] = crime_anal['절도검거']/crime_anal['절도발생']*100
crime_anal['폭력검거율'] = crime_anal['폭력검거']/crime_anal['폭력발생']*100

- 새로운 칼럼 5개를 추가한다. 각 검거에 대한 검거율 값들이다.

del crime_anal['강간검거']
del crime_anal['강도검거']
del crime_anal['살인검거']
del crime_anal['절도검거']
del crime_anal['폭력검거']
crime_anal.head()

- 그리고 5개의 칼럼을 삭제한다.

--> 결과

[11]

crime_anal

--> 결과

- 도봉구 살인 검거율에 NaN이 있다.

- 이는 살인 발생 값이 0이 되어서 연산 오류가 일어난것이다.

 

---

 

crime_anal=crime_anal.fillna(0)
crime_anal

- NaN값을 없애기 위해 fillna함수를 이용해 결측값을 원하는 값으로 변경한다.

--> 결과

[12]

col_list = ['강간검거율', '강도검거율', '살인검거율', 
            '절도검거율', '폭력검거율']
for column in col_list:
    crime_anal.loc[crime_anal[column] > 100, column] = 100
    
crime_anal

- 해당 컬럼들중 수치가 100퍼가 넘어가는 값들을 전부 100으로 바꾸어준다.

--> 결과

[13]

crime_anal.rename(columns = {'강간발생':'강간', 
                             '강도발생':'강도', 
                             '살인발생':'살인', 
                             '절도발생':'절도', 
                             '폭력발생':'폭력'}, inplace=True)
crime_anal.head()

- 발생이 붙은 칼럼 값들을 간단하게 바꾸어준다.

--> 결과

4) 코딩문

[1]

- scikit-learn 라이브러리를 설치한다.

- conda install scikit-learn

- scikit-learn은 파이썬 프로그래밍 언어용 자유 소프트웨어 기계 학습 라이브러리이다.

 

[2]

from sklearn import preprocessing

col = ['강간', '강도', '살인', '절도', '폭력']
x = crime_anal[col].values

- 사이킷런 라이브러리를 선언하고 해당 칼럼들에 대한 값을 받는다.

 

[3]

print(type(x))

--> 결과

<class 'numpy.ndarray'>

---

print(x.dtype)

--> 결과

float64

 

[4]

print(x[:3])

--> 결과

[[7.080e+02 1.400e+01 6.000e+00 2.951e+03 3.677e+03]
 [1.880e+02 1.500e+01 3.000e+00 1.640e+03 1.942e+03]
 [1.590e+02 5.000e+00 9.000e+00 7.800e+02 1.817e+03]]

---

min_max_scaler=preprocessing.MinMaxScaler()
x_scaled=min_max_scaler.fit_transform(x)
print(x_scaled[:3])

- MinMaxScaler함수로 정규화로 전처리한다.

- 정규화는 모든 값을 0~1사이의 값으로 바꾸는 것이다. 음수도 전부다 바뀐다.

- ( X- (X의 최솟값) ) / ( X의 최댓값 - X의 최솟값 ) 이다.

- fit_transformers(): 객체를 생성해 표준화와 마찬가지로 fit으로 학습시킨뒤 transform을 사용해 변환한다.

--> 결과

[[1.         0.92857143 0.4        0.89488871 0.87517832]
 [0.16932907 1.         0.2        0.35449299 0.2564194 ]
 [0.12300319 0.28571429 0.6        0.         0.21184023]]

[5]

crime_anal_norm = pd.DataFrame(x_scaled, columns=col, 
                              index = crime_anal.index)
crime_anal_norm

- 표준화한 값을 이용해 dataframe으로 만든다.

- x_scaled 데이터로 DataFrame의 데이터를 생성한다.

- columns: 각 칼럼에 대한 라벨을 추가한다.

- index: 각 행에 대한 라벨을 추가한다.

--> 결과

[6]

col2 = ['강간검거율', '강도검거율', '살인검거율', 
         '절도검거율', '폭력검거율']
crime_anal_norm[col2] = crime_anal[col2]
crime_anal_norm.head()

- crime_anal_norm 데이터프레임에 새로운 칼럼을 추가한다.

--> 결과