정형 데이터의 전처리 / 탐색 /시각화
정형 데이터 ?
엑셀형태의 수치형 데이터 , 행방향이던 열이던 연산을 할 수 있다.
반정형 데이터
텍스트 데이터 , 구조는 있으나 이걸가지고 수학적인 계산을 할 수는 없다. 결국 비정형데이터에 있는 문서이다.
비정형 데이터
어디에나 있는 데이터 글, 사진,음성 등등
==> 비정형데이터를 정형데이터로 바꿀 수 있다.
ex> 가로세로가 10px 짜리가 있다. 흑백 image 를 픽셀단위로 작게 자르면 1*1의 0~1사이의 숫자로 표현할 수 있다(w/b) / image한장은 백개의 픽셀이 늘어져 있는 형태로 바꿀 수 있다.
0~1 의 1행 * 100열
다양한 툴들이 있다.
Google Analytics(facebook Naver..)
Elastic stack (kibana, Elastic search, Logstash)
Zeppelin
타사의 데이터
Use API & Web srcaper
APIs(twitter, facebook, intagram)
Bots(web crawler , web scraper)
왜 API열어놓지?
서비스의 가치가 올라간다.
서버가 표적이 많이 된다. (허락한 데이터만 가져가!)
이런 API는 성능떨어지는 것이다.
opendata
국가 통계포털
MDIS
etc
Awesome Public Datasets(깃헙)
Google Dataset Search
Kaggle competition datasets 등
read_clipboard
웹상에서 테이블 가져올 수 있다.
read_excel
엑셀파일 가져올 수 있다.
Pandas tutorial (for practice)
import numpy as np
import pandas as pd
import seaborn as sns
df = pd.read_excel('animals.xlsx', encoding='utf-8') # Shift+Tap!
df #DataFrame, Series
df.head() # 머리!
df.tail() # 꼬리!
df.describe() #전반적인 분포
df.info()#몇개의 비어있지 않은 데이터가 있는지
df['name'].head() # 하나의 열 출력하기
df[['name', 'hair', 'feathers']].head() # 여러개의 열 출력하기
sample_dict= {'Dog':'멍멍' ,'Cat' :'야옹'}
sample_dict['Dog'] ##'멍멍'
df_new = df['name', 'hair', 'feathers', 'eggs', 'milk', 'type'] # 에러
#--->리스트로 꺼내야 한다.
df_new = df[ ['name', 'hair', 'feathers', 'eggs', 'milk', 'type'] ]
df_new.head()
# hair 열에 1을 더한 새로운 열을 new_hair 로 추가하기 ______1)
df_new['new_hair'] = df_new['hair'].apply(lambda x : x+1) # '적용하다' 를 영어로?
df_new.head()
# Type 을 index 로 하는 새로운 df 만들기 (엑셀의 pivot table 과 유사) ___2)
pivot_df = pd.pivot_table(df_new, index='type', aggfunc=np.sum) # Shift+Tab! 원본데이터 타입 로드받음 / type이 기준이다.
pivot_df = pd.pivot_table(df_new, index='type', aggfunc=np.max) #mean도 가능
#type 마다 여러개의 행들이 묶여있다. 어떤 것을 가져올거냐 numpy에 있는 sum함수를 가져온다 max함수를 가져온다 라는의미
# 열 삭제하기
#new_hair가 필요하지 않다면?
del pivot_df['new_hair']
pivot_df
# 행 삭제하기
pivot_df = pivot_df.drop([3]) # Database 에서 data point 를 drop! 3이라는 행을 찾아서 지운다.
#리스트로 여러개의 행을 줄 수 있다
# 열 이름 바꾸기
# '이름을 바꿔주다'?
new_pivot = pivot_df.rename(columns = {'eggs':'산란', 'feathers':'깃털'})
new_pivot.head()
##이것을 ---->
pivot_df.rename(columns = {'eggs':'산란', 'feathers':'깃털'}, inplace=True)
pivot_df.head() # inplace 옵션 == 덮어쓰기 여부이다. 안하면 줄이 안바뀐다.
# 이렇게 바꿔준다.
#열이름을 통째로 바꿔주려면 ?
pivot_df.columns = [~,~,~,~] #이런식으로 쓰면 된다.
# 산란 수 기준으로 정렬하기
pivot_df.sort_values(by='산란', inplace=True) # 내용(value)을 기준으로 정렬(sort), inplace=True : 덮어쓰기
pivot_df.head()
# 산란 수 기준으로 내림차순 정렬하기
pivot_df.sort_values(by='산란',ascending =False, inplace=True)
pivot_df.head()
# 얕은 복사와 깊은 복사
pivot_df_2 = pivot_df # shallow copy
pivot_df_3 = pivot_df.copy() # deep=True, deep copy
del pivot_df['산란']
pivot_df_2.head(3) # 원본 DataFrame인 pivot_df와 연결되어 있습니다.
pivot_df_3.head(3) # 원본 DataFrame인 pivot_df로부터 분리되어 별도로 존재합니다.
1) 번 추가 설명
name | hair | feathers | eggs | milk | type | |
---|---|---|---|---|---|---|
0 | aardvark | 1 | 0 | 0 | 1 | 1 |
1 | antelope | 1 | 0 | 0 | 1 | 1 |
2 | bass | 0 | 0 | 1 | 0 | 4 |
3 | bear | 1 | 0 | 0 | 1 | 1 |
4 | boar | 1 | 0 | 0 | 1 | 1 |
--> new_hair 추가
name | hair | feathers | eggs | milk | type | new_hair | |
---|---|---|---|---|---|---|---|
0 | aardvark | 1 | 0 | 0 | 1 | 1 | 2 |
1 | antelope | 1 | 0 | 0 | 1 | 1 | 2 |
2 | bass | 0 | 0 | 1 | 0 | 4 | 1 |
3 | bear | 1 | 0 | 0 | 1 | 1 | 2 |
4 | boar | 1 | 0 | 0 | 1 | 1 | 2 |
2)번추가설명
eggs | feathers | hair | milk | new_hair | |
---|---|---|---|---|---|
type | |||||
1 | 1 | 0 | 39 | 41 | 80 |
2 | 20 | 20 | 0 | 0 | 20 |
3 | 4 | 0 | 0 | 0 | 5 |
4 | 13 | 0 | 0 | 0 | 13 |
5 | 4 | 0 | 0 | 0 | 4 |
6 | 8 | 0 | 4 | 0 | 12 |
7 | 9 | 0 | 0 | 0 | 10 |
데이터 입력및 데이터 전처리
데이터 탐색
데이터 시각화
3. 서울시 범죄현황 통계자료 분석 및 시각화 (for practice)
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib import font_manager, rc # rc == run configure(configuration file)
데이터 입력 및 데이터 전처리
# 서울시 관서별 5대 범죄 발생 & 검거 현황 @ data.go.kr
# 원본 데이터 및 전처리 작업을 위한 파이썬 코드 @ folder named [ Original data source & data preprocessing (5대범죄 & 인구수) ]
df = pd.read_excel('관서별 5대범죄 발생 및 검거.xlsx', encoding='utf-8') # 엑셀 파일 읽기?
df.head() # 데이터의 윗 부분만 살펴보려면?
--> 구별 데이터를 만들고 싶다
경찰서를 구별로 정리하기
# 서울시 경찰청의 소속 구 @ https://goo.gl/MQSqXX
police_to_gu = {'서대문서': '서대문구', '수서서': '강남구', '강서서': '강서구', '서초서': '서초구',
'서부서': '은평구', '중부서': '중구', '종로서': '종로구', '남대문서': '중구',
'혜화서': '종로구', '용산서': '용산구', '성북서': '성북구', '동대문서': '동대문구',
'마포서': '마포구', '영등포서': '영등포구', '성동서': '성동구', '동작서': '동작구',
'광진서': '광진구', '강북서': '강북구', '금천서': '금천구', '중랑서': '중랑구',
'강남서': '강남구', '관악서': '관악구', '강동서': '강동구', '종암서': '성북구',
'구로서': '구로구', '양천서': '양천구', '송파서': '송파구', '노원서': '노원구',
'방배서': '서초구', '은평서': '은평구', '도봉서': '도봉구'}
# dict[칼럼명].apply(칼럼 내 데이터마다 적용할 함수)
# dict.get(key)는 value 를 return
df['구별'] = df['관서명'].apply(lambda x: police_to_gu.get(x, '구 없음')) # 적용하다?
df.head()
# 관서별 데이터를 구별 데이터로 변경 (index : 관서 이름 -> 구 이름, column은 자동으로 오름차순 정렬됨)
# 같은 구의 경우에는 sum 을 적용
gu_df = pd.pivot_table(df, index='구별', aggfunc=np.sum) # 피봇 테이블을 만드려면? / sum은 무슨역할? : 중부에는 남대무서도 있다 하나의 구에 2개이상 경찰서가 있다. 그런 상태에서 너가 원하는 계산이 뭐냐? 강도,살인등 건수를 경찰서별로 범죄를 합산해줘라!
gu_df
gu_df = gu_df.drop(['구 없음']) # 행을 삭제할 때? (Database)
gu_df
범죄별로 검거율 계산하기
# 발생건수 대비 검거건수 -> 검거율 데이터 column을 범죄별로 생성
gu_df['강간검거율'] = gu_df['강간(검거)']/gu_df['강간(발생)']*100
gu_df['강도검거율'] = gu_df['강도(검거)']/gu_df['강도(발생)']*100
gu_df['살인검거율'] = gu_df['살인(검거)']/gu_df['살인(발생)']*100
gu_df['절도검거율'] = gu_df['절도(검거)']/gu_df['절도(발생)']*100
gu_df['폭력검거율'] = gu_df['폭력(검거)']/gu_df['폭력(발생)']*100
gu_df['검거율'] = gu_df['소계(검거)']/gu_df['소계(발생)']*100
# 필요없는 column 지우기 (범죄별 발생 건수와 검거율만 남긴다)
# df.drop(['row']) : 해당 행 데이터를 drop
# del df['column'] : 해당 열 데이터를 drop
# 여러 줄을 한번에 수정할 때
del gu_df['강간(검거)']
del gu_df['강도(검거)']
del gu_df['살인(검거)']
del gu_df['절도(검거)']
del gu_df['폭력(검거)']
del gu_df['소계(발생)']
del gu_df['소계(검거)'] #한꺼번에 한다면? ctrl누르고 마우스로 하나하나 선택한 후에 수정
# 발생건수는 2016이고, 그 전에 발생한 범죄에 대한 검거가 2016에 이뤄지면 검거수에 반영된 것
# if 문을 쓸 필요 없이 바로 boolean 체크 후 값 대입 적용이 가능
gu_df[ gu_df[['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']] > 100] = 100
gu_df.head(10)
# gu_df[['강간검거율', '강도검거율', '살인검거율', '절도검거율', '폭력검거율']] 는 특정한 데이터만 꺼내는 것 이게 100보다 크면? 100으로 바꿔줘라!
# 새롭게 이름을 지어줄 때?
gu_df.rename(columns = {'강간(발생)':'강간',
'강도(발생)':'강도',
'살인(발생)':'살인',
'절도(발생)':'절도',
'폭력(발생)':'폭력'}, inplace=True) # inplace 옵션 == 덮어쓰기 여부
인구 데이터 merge 하기
popul_df = pd.read_csv('pop_kor.csv', encoding='UTF-8') # CSV 는 어떻게 읽을까요? (엑셀과 유사)
# merge하려면 인덱스 열이 같아야 한다.
# 구별 index 를 기준으로 merge를 할 것이므로, index 를 세팅해주기
popul_df = pd.read_csv('pop_kor.csv', encoding='UTF-8', index_col='구별')
# 아래와 같이 먼저 read_csv()하고 .set_index()를 적용할 수도 있습니다.
# popul_df = pd.read_csv('pop_kor.csv', encoding='UTF-8').set_index('구별')
# 데이터프레임의 M&A
gu_df = gu_df.join(popul_df) # df1.join(df2) : df1 의 index를 기준으로 df2 의 index 중 매칭되는 값을 매김
# df.join() 대신 pd.merge()를 사용하여 Merge할 수 있다.
# gu_df = pd.merge(gu_df, popul_df, left_index=True, right_index=True)
# gu_df.head()
데이터 시각화&차트
데이터 살펴보기 (Data exploration)
# 검거율 기준으로 오름차순 정렬하기
# '값'을 기준으로 정렬할 때?
gu_df.sort_values(by='검거율', ascending=False, inplace=True) # ascending=False : 내림차순, inplace=True : 덮어쓰기
gu_df.head()
import seaborn as sns
sns.heatmap(gu_df[['강간', '강도','살인','절도', '폭력']])
#시각화 하기
시각화하면 깨진다 -> 해결
Min-max algorithm을 쓴다(=정규화) : 열의 최소값이 0 열의 최대값이 1이 되게 맞춰준다. (newX = oldX -min(열) / max(열) - min(열)) ---> 직관적임
Standardization 을 쓴다 : 열마다의 평균값을 0으로 맞춰주고 표준편차의 값을 1로 맞춰준다. (newX = oldX -mean(열) / std(열)) ----> 성능이 좋음
범죄별 발생 건수 정규화하기 (범죄별로 가장 많이 발생한 구가 1 == 100%)
# 5대 범죄별 수치를 해당 범죄별 최대값으로 나눠줌
target_col = ['강간', '강도', '살인', '절도', '폭력']
weight_col = gu_df[target_col].max()
weight_col
# target_col은 5개의 열 이것을 weight_col로 나누기 한다.
crime_count_norm = gu_df[target_col]/weight_col
crime_count_norm
한글 데이터 시각화를 위한 준비
# jupyter notebook 내에 figure를 보여주기
%matplotlib inline
# matplotlib의 한글문제를 해결
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
# font_name
rc('font', family=font_name)
## Mac OS
# rc('font', family="AppleGothic")
구별 살인 발생 순위 살펴보기
sns.heatmap(crime_count_norm.sort_values(by='살인', ascending=False)) # 내림차순으로 정렬하려면?
import matplotlib.pyplot as plt
plt.figure
# 몇 가지 옵션으로 더 내용을 확인하기 편하도록 수정하기
# 전체 figure 의 사이즈를 조정
plt.figure(figsize = (10,10))
# annot : 셀 내에 수치 입력 여부
# fmt : 셀 내 입력될 수치의 format (f == float)
# linewidths : 셀 간 이격거리 (하얀 부분, 내부 테두리)
# cmap : matplotlib colormap @ https://goo.gl/YWpBES
sns.heatmap(crime_count_norm.sort_values(by='살인', ascending=False), annot=True, fmt='f', linewidths=.5, cmap='Reds')
plt.title('범죄 발생(살인발생으로 정렬) - 각 항목별 최대값으로 나눠 정규화')
plt.show()
# 살인 대신 절도 기준으로 살펴보기
plt.figure(figsize = (10,10))
sns.heatmap(crime_count_norm.sort_values(by=?, ascending=False), annot=True, fmt='f', linewidths=.5, cmap='RdPu')
plt.title('범죄 발생(절도발생으로 정렬) - 각 항목별 최대값으로 나눠 정규화')
plt.show()
(단순히 범죄건수만 보지 말고) 인구수로 나눠서 인구대비 발생비율로 살펴보기
crime_count_norm.head(3)
gu_df.head(3)
# 행(구)별로 구별 범죄 수 (max 대비 비율값) / 구별 인구 수 * 100000
# 인구 수 단위인 10만을 곱해준다 (강서구 강간 = 9.795665e-07 -> 0.x 까지 끌어올리기)
crime_ratio = crime_count_norm.div(gu_df['인구수'], axis='index') * 100000
crime_ratio.head()
[ 인구수 대비 ] 구별 살인 발생 순위 살펴보기
plt.figure(figsize = (10,10))
sns.heatmap(crime_ratio.sort_values(by='살인', ascending=False), annot=True, fmt='f', linewidths=.5, cmap='Reds')
plt.title('범죄 발생(살인발생으로 정렬) - 각 항목을 정규화한 후 인구로 나눔')
plt.show()
[ 인구 수 대비 ] 구별 5대범죄 발생 수치 평균
# 구별 인구 대비
crime_ratio['전체발생비율'] = crime_ratio.mean(axis=1) # 평균?
crime_ratio.head()
[ 인구 수 대비 ] [ 5대범죄 발생 수치 평균 ] 기준 구별 순위 비교
plt.figure(figsize = (10,10))
sns.heatmap(crime_ratio.sort_values(by='전체발생비율', ascending=False), annot=True, fmt='f', linewidths=.5, cmap='Reds')
plt.title('범죄 발생(전체발생비율로 정렬) - 각 항목을 정규화한 후 인구로 나눔')
plt.show()
'CS > DataAnalysis' 카테고리의 다른 글
데이터 분석 (0) | 2021.04.11 |
---|---|
데이터 분석_설치환경구축, 라이브러리 (0) | 2021.03.28 |
Bigdata analytics (0) | 2019.02.19 |