SlideShare a Scribd company logo
1 of 126
Download to read offline
파이썬
데이터과학
이태영
se2n@naver.com
파이썬을 이용한 데이터 분석,
그리고 머신러닝 실전 입문
1일차
이태영서울시립대 컴퓨터과학부 학사
고려대 전자컴퓨터공학과 석사
(경력)
2010 비씨카드 포인트 서비스 개발 업무
2012 FEP/대행승인/스피드비씨 펌뱅킹 개발 업무
2015 FEP 실시간 분석 모니터링 시스템 개발 구축
2015 BC 집현전 대상 ‘오픈소스를 활용한 빅데이터 플랫폼 구축’
2018 BC R&D Cell 최우수상 ‘AI 기반 서비스 플랫폼 구축’
(특허/논문)
2012, 고객 단말기의 맥 어드레스 정보를 이용한 결제 방법 및 시스템
2013, 고객 단말기의 맥 어드레스 정보를 이용한 결제 방법 및 시스템
2014, 카드 상품 추천 방법 및 카드사 서버
2014, 사용 업종 예측을 위한 카드 사용 패턴 분석 방법 및 수행 서버
2015, 가맹점 개인화 추천 방법 및 가맹점 추천 서버
2017, Scalable 네트워크 아키텍처와 In-memory 컴퓨팅에 기반한
실시간 결제 분석 시스템, 고려대.
2018, Abnormal Payment Transaction Detection Scheme
based on Scalable Architecture and Redis Cluster, IEEE.
무슨 경험으로 강의를 하나요?
@관심사 : Scalable Architecture, Network Architecture, Machine Learning, Object Detection, Visualization, Pattern Recognition
비씨카드 (2010~)
se2n@naver.com
독서백편의자현(讀書百遍義自見)
삽질할 용기
강의자료 100번도 말고
딱 3번만 복습
그리고 궁금하면 질문!
이번 과정을 통해 배울 지식
1. 파이썬 환경
• 개발환경 구축
• jupyter noteobok
2. 데이터 분석
• numpy
• pandas
• 시계열 거래 분석
• 거래 로그 분석 방법
• 선형/다항 회귀 분석
3. 데이터 분석과 시각화
• matplotlib
• seaborn
4. 실전, 데이터분석
• 워드 클라우드
• 지도 시각화
• 19대 대선 결과 분석
• 서울시 부동산 예측 분석
• 자연어처리와 웹 크롤링
5. 머신러닝
• 머신러닝 기초
• 베이지안 네트워크
• 군집화 알고리즘
• 인공신경망
• 추천 시스템
• 마코프 모델과 챗봇
1. 파이썬 환경
파이썬을 배우고 싶어요.
그런데 뭘로 코딩하지?
Eclipse Jupyter
무겁지만 강력하다 빠르고 강력하다
Jupyter
Interactive computing python
• Powerful interactive shells (terminal and Qt-based).
• A browser-based notebook with support for code, text,
mathematical expressions, inline plots and other rich media.
• Support for interactive data visualization and use of GUI toolkits.
• Flexible, embeddable interpreters to load into your own projects.
• Easy to use, high performance tools for parallel computing.
• 대화형 컴퓨팅으로 분석 프로그래밍 최적합
• 운영체제의 쉘 파일 시스템과 통합되어있음
• 웹기반의 대화형 노트북 지원으로 수식, 표, 그림 등을 표현 가능
• 가볍고 빠른 병렬컴퓨팅 엔진 이용
• 코딩과 문서화, 테스트까지 한 화면에 OK
Jupyter
Interactive computing python
• python 3.6.6 설치 (윈도우는 MS Build Tools 2015 이상 함께 설치)
• numpy 설치
• pandas 설치
• ipython 설치
• matplotlib 설치
• jupyter 설치
• notebook 설치
• 인터넷이 잘 된다면
pip install numpy
pip install pandas
pip install ipython
pip install matplotlib
pip install jupyter
pip install notebook
• 인터넷이 차단된 환경이라면
인터넷이 되는 환경에서 패키지들을 다운로드
pip download <패키지들>
다운로드 패키지들을 들여온 다음에 아래 명령어로 설치
pip install --no-index --find-links=. <패키지들>
Jupyter
Interactive computing python
• 패키지 리스트 파일 이용한 설치
• numpy 설치
• pandas 설치
• ipython 설치
• matplotlib 설치
• jupyter 설치
• notebook 설치
• 패키지 리스트 작성 (예, req.txt)
numpy
pandas
ipython
matplotlib
jupyter
notebook
1. 인터넷 설치
pip install -r req.txt
2. 패키지 다운로드 설치
pip download -r req.txt
pip install --no-index --find-links=. -r req.txt
Jupyter
Interactive computing python
Jupyter
Interactive computing python
c = get_config()
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888
c.NotebookApp.token = ''
jupyter_notebook_config.py 설정
$ jupter notebook --generate-config
최초 Config 파일 생성 시 Jupyter 디렉토리 위치
Windows %USERNAME%.jupyter
Linux ~/.jupyter
※비밀번호를 세팅하려면 c.NotebookApp.password 항목에 SHA 값을 설정
Jupyter
Interactive computing python
• 만약 웹서버를 통해 IPytho notebook을 이용할 것이라면 비밀번호 설정 필요
c = get_config()
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.password = u‘sha1:3bf58406dd60:a965f3ac8e10a3637c011ba47dec1d081bbaf834'
c.NotebookApp.port = 8888
In [1]: from notebook.auth import passwd
In [2]: passwd()
Enter password:
Verify password:
Out[2]: 'sha1:3bf58406dd60:a965f3ac8e10a3637c011ba47dec1d081bbaf834‘
• 콘솔창에서 ipython 으로 접속하여서 아래처럼 비밀번호 생성 후 복사
• jupyter_notebook_config.py 에서 password 영역에 붙여넣기
복사 & 붙여넣기
실행 명령어 jupyter notebook
Jupyter Notebook
Web browser based Python IDE
코드를 타이핑 치고
Ctrl+Enter
결과 표시
Jupyter Notebook
파이썬 스크립트 생성
• Notebooks – Python 선택
Jupyter Notebook
파이썬 스크립트 생성
• Notebooks – Python 선택
클릭해서 저장되는
노트북 파일명 변경
Cell은 4가지 형식 존재
Cell 종류 설명
• Code : 파이썬 코드
• MarkDown : 일종의 마크업 언어. 엔하위키나 텀블러에서 사용 중
• Raw NBCovert : IPython 노트북 날 코딩(?)
• Heading : <html>의 <head> 태그와 유사한 기능
Jupyter Notebook
단축키 (Shortcut)
• Edit Mode : 셀 안에서 사용하는 단축키
• Command Mode : 셀 경계에서 사용하는 단축키
• h 를 누르면 기본 단축키에 대해 어느 정도 나온다.
Edit mode 단축키Command mode
단축키
마우스
클릭하고
Jupyter Notebook
단축키 (Shortcut) : Edit Mode 단축키
키보드 기능 키보드 기능
Tab
코드 자동완성,
들여쓰기(intent)
Ctrl-Left 한 단어 좌측 이동
Shift-Tab 툴팁 Ctrl-Right 한 단어 우측 이동
Ctrl-] 들여쓰기(intent) Ctrl-Backspace 이전 단어 삭제
Ctrl-[ 내어쓰기(detent) Ctrl-Delete 이후 단어 삭제
Ctrl-a 전체 선택 Esc command mode
Ctrl-z undo Ctrl-m command mode
Ctrl-Shift-z redo Shift-Enter
run cell,
다음 셀 선택
Ctrl-y redo Ctrl-Enter run cell
Ctrl-Home 셀 처음으로 이동 Alt-Enter
run cell,
다음 셀 삽입
Ctrl-End 셀 끝으로 이동 Ctrl-Shift-- 셀 분할
Ctrl-s 노트북 파일 저장
Jupyter Notebook
단축키 (Shortcut) : Command Mode 단축키
키보드 기능 키보드 기능
Enter Edit mode 진입 c 셀 복사
Shift-Enter run cell, 다음 셀 선택 Shift-v 위에 붙여넣기
Ctrl-Enter run cell v 아래 붙여넣기
Alt-Enter run cell, 다음 셀 삽입 x 셀 잘라내기
y Code 셀로 변환 dd 셀 삭제
m Markdown 셀로 변환 z undo 이전 삭제 복구
r Raw NB 셀로 변환 Shift-m 아래 셀과 병합(merge)
1 Markdown : H1 s 노트북 저장
2 Markdown : H2 Ctrl-s 노트북 저장
3 Markdown : H3 l 해당 셀의 라인번호 토글
4 Markdown : H4 o 결과값 토글
5 Markdown : H5 Shift-o 결과값 토글(scrolling)
6 Markdown : H6 h keyboard shortcuts
a 위에 셀 삽입 ii interrupt kernel
b 아래 셀 삽입 00 restart kernel
k / 방향키 위 이전 셀로 이동 j / 방향키 아래 다음 셀로 이동
Jupyter Notebook
Cell : Markdown
• Markdown language 기반으로 Document 작성 (Wikipedia처럼 작성 방식)
• 코드에 대한 설명이 가능하다.
• 수학수식 표현도 가능 (Mathjax)
내용을 적고
Ctrl+Enter
Jupyter Notebook
Cell : Markdown
• 제목(Head 태그)
# 텍스트
# 하나를 쓰면 HTML의 <h1> 태그
# 두개를 쓰면 HTML의 <h2> 태그. 최대 6개까지 쓸 수 있다.
• 리스트 (li 태그)
• 번호 없는 리스트 : -텍스트 , +텍스트, *텍스트
• 번호 있는 리스트 : 숫자.텍스트
• 기울인 글씨(Italic 태그) : _텍스트_ , *텍스트*
• 굵은 글씨(Strong 태그) : __텍스트__ , **텍스트**
• 인용(cite) : >텍스트
• 인라인 링크 : [텍스트](링크)
• 수평선(hr 태그) : --- , *** , ___
Jupyter Notebook
Cell : Code
• 파이썬의 코드를 각 셀에 원하는 만큼을 작성하여 실행하면 메모리 상에 반영된다.
• 위, 아래 위치가 달라도 실행한 스텝 번호(In [번호])가 높을 수록 최근에 수행된 영역이다.
방향 버튼을 이용하여
Cell의 위치를 변경 가능
Jupyter Notebook
Magic Keyword (매직 명령어)
• 자주 사용하는 IPython 매직 명령어
• %(명령어) : 셀 내의 라인 독립 실행
• %%(명령어) : 셀 내의 전체 내용 관련 실행
매직 명령어 기능
%quickref IPython의 빠른 도움말 표시
%magic 모든 매직 함수에 대한 상세 도움말 출력
%debug 최근 예외 트레이스백의 하단에서 대화형 디버거로 진입
%hist 명령어 입력(그리고 선택적 출력) history 출력
%pdb 예외가 발생하면 자동으로 디버거로 진입
%run script.py IPython 내에서 파이썬 스크립트 실행
%timeit statement
statement를 여러차례 실행한 후 평균 실행 시간을 출력. 매우 짧은 시간 안에 끝
나는 코드의 시간을 측정할 때 유용
%%writefile 파일명 filename인 파일을 생성
%save 파일명 from-to IPython의 이미 실행된 Step번호 구간대 명령어를 파일로 저장
Jupyter Notebook
Magic Keyword (매직 명령어)
• 자주 사용하는 IPython 매직 명령어
• %(명령어) : 셀 내의 라인 독립 실행
• %%(명령어) : 셀 내의 전체 내용 관련 실행
Jupyter Notebook
Magic Keyword (매직 명령어) : TIP
• (리눅스/유닉스만) %%writefile으로 스크립트 저장 후 %run으로 실행하려면
파이썬 스크립트에 한글이 포함될 때는 #!(샤방) 파이썬 패스, 언어 타입 정의 필요하다.
#!/usr/bin/python
#-*- coding: utf-8
Jupyter Notebook
운영체제와 함께 사용하기
• IPython에서 운영체제의 자체 명령어를 실행하기 위해서는 !(명령어)로 수행
Jupyter Notebook
운영체제와 함께 사용하기
• !(명령어)로 수행된 출력결과를 IPython의 데이터로 사용 가능
Jupyter Notebook
ipdb 디버깅을 이용한 코드 분석
• 매직 명령어 %debug 혹은 %%debug
Jupyter Notebook
ipdb 디버깅을 이용한 코드 분석
• ipdb 명령어
명령어 설명
h help
디버그 도움말. h만 입력하면 디버그 명령어 리스트 출력
h [명령어]를 입력하면 [명령어]에 대한 이용 도움말
w where 현재 위치의 Stack trace 출력
s step 현재 라인을 실행하고 다음 스텝으로 이동
n next 현재 라인을 실행하고 다음 라인으로 이동
r return 현재 함수가 끝날 때(return)까지 계속 실행
b break 특정 라인에 break point 설정
c continue break point가 있을 때까지 계속 실행
a args 현재 함수에 할당된 argument를 출력
p print value를 출력
cl clear [args] clear break point
d down 현재 Stack에서 하위 Strack frame으로 이동
u up 현재 Stack에서 상위 Stack frame으로 이동
l list [from,to] 소스 출력
run run [args] Restart 디버거 프로그램. [args]을 입력하면 sys.argv에 할당됨
q quit 디버깅 종료
Jupyter Notebook
ipdb 디버깅을 이용한 코드 분석
• h (help) 명령어
Jupyter Notebook
ipdb 디버깅을 이용한 코드 분석
• step , up, down 명령어
In [8]:
def A():
print 'world'
def B():
print 'hello'
A()
ipdb> b 5
Breakpoint 1 at <ipython-input-8-c7a559c3b1ab>:5
ipdb> c
hello
> <ipython-input-8-c7a559c3b1ab>(5)B()
3 def B():
4 print 'hello'
1---> 5 A()
ipdb> s
--Call--
> <ipython-input-8-c7a559c3b1ab>(1)A()
----> 1 def A():
2 print 'world'
3 def B():
ipdb> s
> <ipython-input-8-c7a559c3b1ab>(2)A()
1 def A():
----> 2 print 'world'
3 def B():
ipdb> u
> <ipython-input-8-c7a559c3b1ab>(5)B()
3 def B():
4 print 'hello'
1---> 5 A()
ipdb> d
> <ipython-input-8-c7a559c3b1ab>(2)A()
1 def A():
----> 2 print 'world'
3 def B():
A 함수로 진입
상위 Stack으로 이동
하위 Stack으로 이동
다음 스텝
%debug B()
• ipdb 명령어
명령어 설명
h help
디버그 도움말. h만 입력하면 디버그 명령어 리스트 출력
h [명령어]를 입력하면 [명령어]에 대한 이용 도움말
w where 현재 위치의 Stack trace 출력
s step 현재 라인을 실행하고 다음 스텝으로 이동
n next 현재 라인을 실행하고 다음 라인으로 이동
r return 현재 함수가 끝날 때(return)까지 계속 실행
b break 특정 라인에 break point 설정
c continue break point가 있을 때까지 계속 실행
a args 현재 함수에 할당된 argument를 출력
p print value를 출력
cl clear [args] clear break point
d down 현재 Stack에서 하위 Strack frame으로 이동
u up 현재 Stack에서 상위 Stack frame으로 이동
l list [from,to] 소스 출력
run run [args] Restart 디버거 프로그램. [args]을 입력하면 sys.argv에 할당됨
q quit 디버깅 종료
Jupyter Notebook
ipdb 디버깅을 이용한 코드 분석
2. Numpy
Numpy
기초 사용법
• Numerical Python
• C언어로 구현된 저수준 고성능 라이브러리
• 반복문을 작성할 필요 없이 전체 데이터 배열에 대한 빠른 연산 지원
• 배열 데이터를 디스크에 쓰거나 읽을 수 있는 도구와 메모리에 올려진 파일에 사용하는 도구
• 빠르고 메모리를 효율적으로 사용하여 다차원 배열 ndarray 지원
• 선형대수, 난수 발생기, 푸리에 변환 기능
import numpy as np
ar_list = [i for i in range(20)]
np_list = np.array(ar_list)
%%timeit np_list * 100
661 ns ± 6.17 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit ar_list * 100
4.04 µs ± 33.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Numpy
기초 사용법
• 스칼라/벡터/행렬
• 스칼라는 number
• 벡터(vector)는 숫자들의 list
• 행렬(matrix)는 숫자들의 array(rows, columns)
Numpy
기초 사용법
• numpy 배열 (1/2)
• numpy 배열을 만들 때는 np.array() 메소드 이용
• np.array()는 파이썬의 리스트를 numpy,ndarray 형태로 변환
• numpy는 다차원 행렬로 표현하고, 계산하기 쉬움
arr = [[1,2,3,4], [5,6,7,8]]
arr2= np.array(arr)
arr2.ndim
Out[]:2
arr2.shape
Out[]:(2, 4)
arr2 * 10
Out[]: array([[10, 20, 30, 40], [50, 60, 70, 80]])
arr2 + 10
Out[]: array([[11, 12, 13, 14], [15, 16, 17, 18]])
Numpy
기초 사용법
• numpy 배열 (2/2)
• zeros : 0으로 초기화된 배열, ones : 1로 초기화된 배열
• linespace : 선형 구간에서 지정 구간의 수만큼 분할
• logspace : 로그 구간에서 지정 구간의 수만큼 분할
• empty : 배열을 메모리에 생성만하고 특정한 값을 초기화하지 않는 배열 (초기화 시간 단축)
np.zeros(5)
Out[]: array([0., 0., 0., 0., 0.])
np.ones(5)
Out[]: array([1., 1., 1., 1., 1.])
np.linspace(0, 10, 5) # (시작, 끝, 개수)
Out[]: array([ 0. , 2.5, 5. , 7.5, 10. ])
np.logspace(0, 100, 5)
Out[]: array([1.e+000, 1.e+025, 1.e+050, 1.e+075, 1.e+100])
np.empty(5)
Out[]: array([0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000,
0.00000000e+000, 0.00000000e+000, 1.70704615e-312])
Numpy
기초 사용법
• numpy 산술 연산
• numpy는 배열과 스칼라 값을 조합으로 산술 연산이 가능
• numpy 배열은 스칼라 값에 의해 원소별(element-wise)로 한 번씩 수행 (브로드캐스트)
arr = np.array([[1,2,3,4], [5,6,7,8]] )
arr * 10
Out[]: array([[10, 20, 30, 40], [50, 60, 70, 80]])
arr + 10
Out[]: array([[11, 12, 13, 14], [15, 16, 17, 18]])
arr / 2
Out[]: array([[0.5, 1. , 1.5, 2. ],
[2.5, 3. , 3.5, 4. ]])
arr % 2
Out[]: array([[1, 0, 1, 0],
[1, 0, 1, 0]], dtype=int32)
Numpy
기초 사용법
• 다차원으로 변환
• numpy는 배열은 reshape로 N차원 매트릭스로 변환 가능
• reshape 명령어 중 원소는 -1로 대체할 수 있다.
• arr.reshape(4,-1) : 4개 ROW를 가지는 행렬
• arr.reshape(-1,5) : 5개 COLUMN을 가지는 행렬
arr = np.array(range(0,20)) # 0~19까지 생성
arr_2d = arr.reshape(4,5)
arr_2d
Out[]: array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
arr.reshape(4,-1)
arr.reshape(-1, 5)
Out[]: array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
Numpy
기초 사용법
• 다차원으로 변환
• flatten 메소드 : numpy 다차원 배열을 1차원 리스트로 변환
• np.newaxis :차원을 증가시킬 때 사용
arr_3d = arr.reshape(5, 2, 2)
arr_2d.reshape(1,20)
Out[]: array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
arr_1d = arr_3d.flatten()
arr_1d
Out[]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,17, 18, 19])
arr_1d[np.newaxis]
Out[]: array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
arr_1d[np.newaxis, np.newaxis]
Out[]: array([[[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]])
Numpy
배열 붙이기
• 행(COLUMN)의 수나 열(ROW)의 수가 같은 두 개 이상의 배열을 잇는(concatenate) 방법
• hstack : ROW의 수가 같은 경우, COLUMN으로 붙임 (좌측에서 옆으로 붙임)
• vstack : COLUMN의 수가 같은 경우, ROW으로 붙임 (위에세서 아래로 붙임)
• stack : 배열을 별개 차원으로 구성한다. (2차원 배열 두 개를 합치면 3차원 배열로.)
a1 = np.ones((3,4)) #1로 채워진 배열 생성
a2 = np.zeros((3,4)) #0으로 채워진 배열 생성
np.hstack([a1, a2])
Out[]: array([[1., 1., 1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0., 0., 0.]])
np.vstack([a1,a2])
Out[]: array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
np.stack([a1,a2])
Out[]: array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
#axis=1 지정 시각 배열의 row별 묶음
np.stack([a1,a2], axis=1)
array([[[1., 1., 1., 1.],
[0., 0., 0., 0.]],
[[1., 1., 1., 1.],
[0., 0., 0., 0.]],
[[1., 1., 1., 1.],
[0., 0., 0., 0.]]])
Numpy
기술통계
• 집계 합수(aggregate function)
• max (배열의 최대값) min (배열의 최소값) mean (배열의 평균 값)
• numpy의 모든 집계 함수는 AXIS 기준으로 계산이 이루어짐
arr = np.array([[5,6,7,8,9], [0,1,2,3,4]])
arr.max()
Out[]: 9
arr.min()
Out[]: 0
arr.mean()
Out[]: 4.5
arr.max(axis=1)
Out[]: array([9, 4])
arr.min(axis=1)
Out[]: array([5, 0])
arr.mean(axis=1)
Out[]: array([7., 2.])
arr.max(axis=0)
Out[]: array([5, 6, 7, 8, 9])
arr.min(axis=0)
Out[]: array([0, 1, 2, 3, 4])
arr.mean(axis=0)
Out[]: array([2.5, 3.5, 4.5, 5.5, 6.5])
Numpy
랜덤 함수
• 난수(random number)
np.random.seed(0) # 랜덤 seed 지정
np.random.randint(0, 1000) # 0~1000사이 난수 생성
Out[]: 629
np.random.rand(5) #5개의 난수 생성
Out[]: array([0.22232139, 0.38648898, 0.90259848, 0.44994999, 0.61306346])
np.random.rand(3,5) #3x5 행렬 형태의 난수 생성
Out[]: array([[0.888609 , 0.90658127, 0.55368029, 0.83453863],
[0.29628516, 0.2548365 , 0.59444402, 0.14268807],
[0.13459794, 0.81022365, 0.69110336, 0.37632546]])
x = np.arange(10) # 0~9까지 배열 생성
Out[]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.random.shuffle(x) # 배열 x의 순서를 무작위로 변경 ()
Out[]: array([5, 0, 4, 2, 3, 6, 8, 7, 9, 1])
Numpy
데이터 샘플링
• 데이터 샘플링
• 샘플링(sampling) : 존재하는 데이터 집합에서 일부를 무작위로 선택
• np.random.choice( a, size=None, replace=True, p=None)
x = np.random.choice(10, 10, replace=False) # shuffle 기능과 동일
Out[]: array([0, 7, 1, 5, 2, 3, 9, 6, 8, 4])
np.random.choice(x, 5, replace=True) # 5개 샘플링, 중복 허용
Out[]: array([2, 4, 6, 3, 6])
np.random.choice(4, 3, replace=False, p=[0.4, 0.2, 0, 0.4]) # 선택 확률 별도 지정
Out[]: array([0, 3, 1])
a 배열, 혹은 정수. 정수를 입력할 경우 range(a) 명령으로 데이터 생성
size 샘플할 개수 지정
replace True이면 한 번 선택한 데이터를 다시 추출 가능 (중복 추출)
p a 배열의 데이터들에 대해 선택될 수 있는 확률 지정
Numpy
비교 연산
• 비교 연산 처리
• 인덱싱 영역에 조건 값을 입력하면 해당 조건에 맞는 데이터 추출 가능
• 인덱싱 영역에 조건 값을 입력하고 해당 조건에 맞는 영역에 새로운 값을 대입 가능
f = np.random.rand(3,4)
Out[]: array([[0.888609 , 0.90658127, 0.55368029, 0.83453863],
[0.29628516, 0.2548365 , 0.59444402, 0.14268807],
[0.13459794, 0.81022365, 0.69110336, 0.37632546]])
tf = f > 0.3
Out[]: array([[ True, True, True, True],
[False, False, True, False],
[False, True, True, True]])
f[ f > 0.3 ] = 1
Out[]: array([[1. , 1. , 1. , 1. ],
[0.29628516, 0.2548365 , 1. , 0.14268807],
[0.13459794, 1. , 1. , 1. ]])
Numpy
유니버설 함수
• ufunc라고 불리는 유니버설 함수.
• ndarray 안에 있는 데이터 원소별로 연산을 수행
• 고속으로 수행할 수 있는 벡터화된 Wrapper 함수
x = np. linspace(-5, 5, 20) # 선형공간 0~10에서 20개 데이터 고르게 추출
np.sqrt(x) # 제곱근 연산 √x
np.exp(x) # 지수함수 연산 ex (e=2.718281…)
np.abs(x) # 절대값 연산
np.ceil(x) # 소수점 올림 연산
np.floor(x) # 소수점 내림 연산
np.round(x) # 소수점 반올림 연산
np.cos(x), np.sin(x) # sin함수, cos함수 처리 (그 외 다양한 삼각함수들 존재)
np.power(x, n) # n 제곱 처리
np.log(x) # 자연로그 연산 (logex)
np.log10(x) # 로그10 연산 (log10x)
np.log2(x) # 로그2 연산 (log2x)
np.mod(x, n) # 각 요소별로 n으로 나눈 뒤의 나머지 추출
Numpy
유니버설 함수
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-5, 5, 100)
y = x
y_sin = np.sin(x)
y_cos = np.cos(x)
y_sqrt = np.sqrt(x)
y_log = np.log(x)
y_log10 = np.log10(x)
fig= plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y, label='y=x')
ax.plot(x, y_sin, label='sin')
ax.plot(x, y_cos, label='cos')
ax.plot(x, y_sqrt, label='sqrt')
ax.plot(x, y_log, label='log')
ax.plot(x, y_log10, label='log10')
ax.legend()
plt.show()
• matplotlib는 이후 데이터시각화에서 다룰 예정
• plot 그래프에 x 좌표, y 좌표에 어떤 데이터가
입력되는지 확인하고 눈으로 보는 데 의의두자!
Numpy
최소제곱법 : 선형회귀
• 최소제곱법 (Method of Least Squares)
• 함수 값과 측정 값의 차이인 오차를 제곱한 것의 합이 최소가 되는 함수 Y = F(X)를 구하는 방법
• f(x) = ax + b의 경우 f(x)를 최소화 하도록 a, b를 결정 짓는 방법
• σ𝑖=1(𝑦𝑖 − 𝑎𝑥𝑖 − 𝑏)2
• 각 데이터 좌표에서 최적함수까지의 거리 구함
• 최적의 함수라면, 이 차이가 가능한 한 최소화
• 최소제곱법은 이 편차를 최소화하기 위한 방법
• 이렇게 나온 선을 최소제곱선 혹은 선형회귀선
측정값
𝑦𝑖
𝑦𝑡𝑟𝑢𝑒
상수항 α
종속변수 𝑦
독립변수 𝑥
오차𝑒𝑖
Numpy
선형회귀(Linear Regression)
• polyfit과 poly1d를 이용한 선형회귀
• np.polyfit(x, y, degree) : 주어진 측정 값들로 다항식의 계수를 구함
• x array, y array값을 입력, degree는 다항식의 차수
• (degree = 1) 1항식 경우 y = ax + b → 리턴 값 array([a, b])
• (degree = 2) 2항식 경우 y = ax2 + bx + c → 리턴 값 array([a, b, c])
• (degree = 3) 3항식 경우 y = ax3 + bx2 + cx + d → 리턴 값 array([a, b, c, d])
• np.poly1d(coefficients) : 다항식 계수로 1차원 다항식 함수 생성
• fx = np.poly1d([1,2,3]) : 1x2 + 2x + 3 식을 갖는 다항식 함수 생성
• fx([1,2,3,4,5]) → x 값으로 1,2,3,4,5를 받아 다항식 fx 함수로 연산
x = np.arange(0, 10, 0.01) # 0~10까지 0.01 단위로 배열 생성
y = 3*x + 5 # 3*x + 5 연산한 배열 생성
y_noise = y + np.random.randn(len(y)) # 랜덤으로 노이즈 생성
fp1 = np.polyfit(t, y_noise, 1) # polyfit 다항식 계수 생성
Out[]: array([3.0042063 , 4.94969849])
fx = np.poly1d(fp1) # poly1d 다항식 1차원 함수 생성
fx([0,1,2,3]) # 함수를 이용한 계산
Out[]: array([ 4.94969849, 7.95390479, 10.95811109, 13.96231739])
Numpy
선형회귀(Linear Regression)
• https://github.com/sh2orc/datascience에서 trns_1day_series 다운로드
import pandas as pd #pandas library
import numpy as np #numpy library
df = pd.read_csv('trns_1day_series')
x = df['APPROVAL'] #승인건수 Series 추출
fp1 = np.polyfit(x.index, x, 1) #1차 다항식 계수
fp2 = np.polyfit(x.index, x, 2) #2차 다항식 계수
fp3 = np.polyfit(x.index, x, 3) #3차 다항식 계수
fx1 = np.poly1d(fp1) #1차 다항식 함수 생성
fx2 = np.poly1d(fp2) #2차 다항식 함수 생성
fx3 = np.poly1d(fp3) #3차 다항식 함수 생성
df['REG_1'] = fx1(x.index) #1차 다항식 연산
df['REG_2'] = fx2(x.index) #2차 다항식 연산
df['REG_3'] = fx3(x.index) #3차 다항식 연산
df[['APPROVAL','REG_1','REG_2','REG_3']].plot()
3. Pandas
Pandas
기초 개념
• Pandas
• Numpy 기반으로 개발되어 고성능 데이터 분석 가능
• R언어에서 제공하는 DataFrame 자료형 제공
• 명시적으로 축의 이름에 따라 데이터 정렬 가능한 자료구조
• 통합된 Time Series 분석 기능
• 누락된 데이터를 유연하게 처리할 수 있는 기능
import numpy as np
import pandas as pd # Pandas 라이브러리 선언
logx = np.logspace(0, 1, 100)
linx = np.linspace(0, 10, 100)
df = pd.DataFrame() #Pandas의 DataFrame 생성
df['logspace'] = logx #컬럼명 logspace의 Series 데이터
df['linspace'] = linx #컬럼명 linespace의 Series 데이터
df.head() # DataFrame 상위 5개 보기
df.plot() # 그래프로 출력
Pandas
기초 개념
• DataFrame
• 레이블(Labeled)된 행(Column)과 열(Row)을 가진 2차원 데이터구조
• 칼럼 마다 데이터 형식이 다를 수 있음
• 각 행(Column)과 열(Row)들을 산술연산이 가능한 구조
• DataFrame 크기는 유동적으로 변경 가능
• DataFrame끼리 여러 가지 조건을 사용한 결합처리 가능
가 나 다 라
A 3 1 7 0
B 8 2 8 0
C 0 3 9 0
D 2 4 0 1
E 1 5 1 0
row
column
Pandas
기초 개념
• Series와 DataFrame
• Series : 인덱스 라벨이 붙은 1차원 리스트 데이터 구조
• DataFrame : Series가 모인 2차원 테이블 데이터 구조 (인덱스와 컬럼 라벨이 붙음)
• DataFrame이 핵심이고, Series는 개념으로 알아두자!
A 3
B 8
C 0
D 2
E 1
가 나 다 라
A 3 1 7 0
B 8 2 8 0
C 0 3 9 0
D 2 4 0 1
E 1 5 1 0
index
column
Series DataFrame
index
Pandas
기초 개념
• Series와 DataFrame
• Series 생성 : pd.Series(values, index=index, names=names)
• DataFrame 생성 : pd.DataFrame(values, index=index, columns=cols)
pd.Series([1,2,3,4], index=['one','two','three','four'])
Out[]:
one 1
two 2
three 3
four 4
dtype: int64
pd.DataFrame([1,2,3,4], index=['one','two','three','four'], columns=['number'])
Out[]:
number
one 1
two 2
three 3
four 4
DataFrame 생성
고객 금액 가맹점 카드
0 A 1000 0001 944020
1 B 2000 0002 480520
2 C 5000 0003 460220
ds = [ {'고객':'A', '금액':1000, '가맹점':'0001', '카드':'9440'},
{'고객':'B', '금액':2000, '가맹점':'0002', '카드':'4805'},
{'고객':'C', '금액':5000, '가맹점':'0003', '카드':'4602'} ]
df = pd.DataFrame(ds)
default
List
RoworientedColumnoriented
ds = { '고객' :['A','B','C'],
'금액' :[1000, 2000, 5000],
'가맹점' :['0001', '0002', '0003'],
'카드' :['9440', '4805', '4602'] }
df = pd.DataFrame.from_dict(ds)
#df = pd.DataFrame(ds) 가능
from_dict from_items
ds = [['고객' ,['A', 'B', 'C']],
['금액' ,[1000, 2000, 5000]],
['가맹점' ,['0001', '0002', '0003' ]],
[ '카드' ,['9440', '4805', '4602' ]] ]
df = pd.DataFrame.from_items(ds)
from_records
Dictionary
ds = [['A', 1000, '0001', '9440'],
['B', 2000, '0002', '4805'],
['C', 5000, '0003', '4602']]
lb = ['고객', '금액', '가맹점', '카드']
df = pd.DataFrame.from_records(ds, columns=lb)
#df = pd.DataFrame(ds, columns=lb) 가능
Pandas
DataFrame 생성
• CSV 형식 파일을 읽어 들여 DataFrame 생성
• pd.read_csv(path, sep='구분자', names=['컬럼명',..]) : 파일로부터 DataFrame 생성
• github.com/sh2orc/datascience에서 데이터셋 다운로드
df = pd.read_csv('titanic.csv', sep='t') #데이터가 TAB으로 구분되어 있는 경우
df.head()
#컬럼 헤더가 없는 파일의 경우는 name= 옵션을 통해 지정해줄 수 있다.
df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26 0 0
STON/O2.
3101282
7.925 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S
MSG_CODE MSG_NAME
0 0100 MS승인요청
1 0110 MS승인응답
2 0300 IC승인 요청
3 0310 IC승인 응답
4 0420 MS승인취소 요청
Pandas
DataFrame 생성
• dictionary 객체로 DataFrame 생성
• dictionary 객체가 단순 {key:value}로 구성되어있을 경우
• pd.from_dict(ds, oriented='index', columns=['value에 대한 칼럼명'])
firm_name={"03":"IBK기업은행", "11":"NH농협은행", "20":"우리카드",
"23":"SC제일은행", "48":"새마을금고", "72":"우체국" }
df = pd.DataFrame.from_dict(firm_name, orient='index', columns=['FIRM_NAME’])
df
FIRM_NAME
03 IBK기업은행
11 NH농협은행
20 우리카드
23 SC제일은행
48 새마을금고
72 우체국
Pandas
Column명 변경
• DataFrame의 rename
• pd.DataFrame.columns = [ '칼럼1', '칼럼2', … , ] 이용
• pd.DataFrame.rename( { 'OLD칼럼명' : 'NEW칼럼명', …, }, axis=1) 이용
• pd.DataFrame.rename(columns={ 'OLD칼럼명' : 'NEW칼럼명', …, }) 이용
df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str)
df.head()
df.rename({'MSG_CODE' : 'CODE'}, axis=1) #둘 다 같은 역할
df.rename(columns={'MSG_CODE' : 'CODE'})
MSG_CODE MSG_NAME
0 0100 MS승인요청
1 0110 MS승인응답
2 0300 IC승인 요청
3 0310 IC승인 응답
4 0420 MS승인취소 요청
CODE MSG_NAME
0 0100 MS승인요청
1 0110 MS승인응답
2 0300 IC승인 요청
3 0310 IC승인 응답
4 0420 MS승인취소 요청
df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str)
df = df.set_index('MSG_CODE')
df['COUNT'] = [ np.random.randint(5,10) for i in range(len(df.index)) ]
df.plot(kind='bar')
MSG_NAME
MSG_CODE
0100 MS승인요청
0110 MS승인응답
0300 IC승인 요청
0310 IC승인 응답
0420 MS승인취소 요청
Pandas
DataFrame Index
• index 지정 방법
• 생성 시점 : pd.read_csv(path, names=[], index_col=칼럼인덱스번호)
• 생성 이후 : pd.DataFrame.set_index('칼럼명')
Index로 지정 시 해당 데이터 컬럼이
데이터의 축이 된다.
Pandas
DataFrame Index
• index 초기화
• reset_index() : 기존 index를 컬럼으로 위치시키고, 새로운 index를 생성한다.
df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str)
df = df.set_index('MSG_CODE')
df['COUNT'] = [ np.random.randint(5,10) for i in range(len(df.index)) ]
df = df.reset_index()
set_index() reset_index()
MSG_CODE MSG_NAME COUNT
0 0100 MS승인요청 9
1 0110 MS승인응답 7
2 0300 IC승인 요청 5
3 0310 IC승인 응답 7
4 0420 MS승인취소 요청 6
MSG_NAME
MSG_CODE
0100 MS승인요청
0110 MS승인응답
0300 IC승인 요청
0310 IC승인 응답
0420 MS승인취소 요청
Pandas
행(Column)과 열(Row) 삭제
• pd.DataFrame.drop([label, …, ], axis=0 또는 1)
• 열(Row) 삭제 - label에 삭제할 row의 index들을 입력
• 행(Colum) 삭제 - label에 삭제할 column들을 입력. 이 때 axis=1로 지정
df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str)
df['COUNT'] = [ np.random.randint(5,10) for i in range(len(df.index)) ]
df.drop([0,1,3]) df.drop('COUNT', axis=1)
MSG_CODE MSG_NAME COUNT
0 0100 MS승인요청 5
1 0110 MS승인응답 7
2 0300 IC승인 요청 7
3 0310 IC승인 응답 8
4 0420 MS승인취소 요청 7
MSG_CODE MSG_NAME COUNT
2 0300 IC승인 요청 7
4 0420 MS승인취소 요청 7
5 0430 MS승인취소 응답 8
6 9300 기타승인 요청 8
7 9310 기타승인 응답 5
MSG_CODE MSG_NAME
0 0100 MS승인요청
1 0110 MS승인응답
2 0300 IC승인 요청
3 0310 IC승인 응답
4 0420 MS승인취소 요청
Pandas
행(Column)과 열(Row) 삭제
• 특정 컬럼 기준으로 삭제 방법
• 칼럼을 index로 지정하고, 삭제할 대상을 각각 하드코딩
• 칼럼을 index를 리스트로 추출하여, 삭제할 대상에 입력
df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str)
tf = df.set_index('MSG_CODE')
tf.drop(['0100','0110']) #index 0100, 0110 기준 ROW 삭제
tf.index.str[:2] == '01'
Out[]: array([ True, True, False, False, False, False, False, False, False, False, False, False])
tf.index[tf.index.str[:2] == '01']
Out[]: Index(['0100', '0110'], dtype='object', name='MSG_CODE')
tf.drop(tf.index[tf.index.str[:2]=='01']) # 01로 시작하는 index 추출 후 ROW 삭제
Pandas
선택과 변경
• DataFrame의 배열[ ] 내 값을 지정한 선택
• 숫자 인덱스 선택 : 열(ROW)
• KEY값으로 선택 : 행(COLUMN)
df = pd.DataFrame( np.arange(9).reshape(3,3), index=['r1','r2','r3'], columns=['c1','c2','c3'])
df[:2] #슬라이싱 인덱스 기준은 ROW
df[['c1','c2']] # [ ] 내에는 KEY 조회는 칼럼만 가능
df['r1'] # KEY 값을 인덱스 KEY로 지정 불가
KeyError: 'r1'
c1 c2 c3
r1 0 1 2
r2 3 4 5
r3 6 7 8
c1 c2 c3
r1 0 1 2
r2 3 4 5
c1 c2
r1 0 1
r2 3 4
r3 6 7
Pandas
선택과 변경
• DataFrame의 배열[ ] 내 (칼럼) 조건 지정
• 해당 지정된 칼럼의 조건에 의한 Boolean 선택
• 2개 이상의 조건은 각 조건별로 ( ) 묶음을 통해 AND/OR 조건 지정
df = pd.DataFrame( np.arange(9).reshape(3,3), index=['r1','r2','r3'], columns=['c1','c2','c3'])
df[df.c1 > 4] #DataFrame 객체의 멤버 변수로 칼럼명 지정 접근
df[df['c1'] > 4] #DataFrame의 배열 Key로 칼럼명 지정 접근
df[(df.c1 > 1) & (df.c2 < 5)] #2개 이상의 조건 지정 때는 각 조건별로 ( )로 묶어줘야 함
c1 c2 c3
r1 0 1 2
r2 3 4 5
r3 6 7 8
c1 c2 c3
r3 6 7 8
c1 c2 c3
r3 6 7 8
c1 c2 c3
r2 3 4 5
Pandas
선택과 변경
• DataFrame의 배열[ ] 내 (칼럼) 조건 지정
• df[ [칼럼명1, 칼럼명2, …, ] ] 형식으로 정의시 DataFrame 재정의 가능
• 재정의된 DataFrame은 마치 가상 뷰(View) 테이블처럼 구성
df = pd.DataFrame( np.arange(9).reshape(3,3), index=['r1','r2','r3'], columns=['c1','c2','c3'])
df[ [‘c1’, ‘c2’] ] #c1, c2 칼럼으로만 DataFrame 재구성
df[ [‘c1’] ] #c1 칼럼으로만 DataFrame 재구성
c1 c2 c3
r1 0 1 2
r2 3 4 5
r3 6 7 8
c1 c2
r1 0 1
r2 3 4
r3 6 7
c1
r1 0
r2 3
r3 6
Pandas
선택과 변경
• loc 인덱스 : 레이블 선택을 기반으로 한 인덱서
• df.loc[ <열 선택 조건> , <행 선택 조건> ]
• 정수형(integer) 위치 지정으로는 선택 불가.
df = pd.DataFrame(np.array([100,20000, 50,50000, 90, 50000]).reshape(3,2),
columns=['성능','가격'], index=['BC1','BC2','BC3'])
df.loc['BC1'] # loc[ ]에 단독 KEY로 입력할 경우 ROW 기준으로 조회
성능 100
가격 20000
Name: BC1, dtype: int32
df.loc['BC1', '가격'] # BC1 열의 '가격' 행의 값을 조회
20000
df.loc[(df.성능 % 50 == 0), "성능"] # 전체 열에서 성능%50 == 0 조건으로 필터링 중 "성능" 칼럼 조회
BC1 100
BC2 50
Name: 성능, dtype: int32
성능 가격
BC1 100 20000
BC2 50 50000
BC3 90 50000
Pandas
선택과 변경
• loc 인덱스 데이터 변경
• df.loc[ <열 선택 조건> , <행 선택 조건> ] = '변경할 값'
• loc를 이용하여 조건에 해당하는 전체 데이터를 변경 가능
df = pd.DataFrame(np.array([100,20000, 50,50000, 90, 50000]).reshape(3,2),
columns=['성능','가격'], index=['BC1','BC2','BC3'])
df.loc[(df.성능 % 50 == 0), "성능"] # 전체 열에서 성능%50 == 0 조건으로 필터링 중 "성능" 칼럼 조회
BC1 100
BC2 50
Name: 성능, dtype: int32
df.loc[(df.성능 % 50 == 0), "성능"] = 70 # 선택된 "성능" 칼럼의 데이터들을 70으로 전체 변경
df
성능 가격
BC1 100 20000
BC2 50 50000
BC3 90 50000
성능 가격
BC1 70 20000
BC2 70 50000
BC3 90 50000
Pandas
정렬 (Sorting)
• df.sort_values(by = [기준 칼럼명,…], ascending=True )
• 기준 컬럼명을 여러 개 지정하면 각 순서별로 정렬 기준
• ascending을 입력하지 않으면 True(오름차순)로 판단
df
df.sort_values('성능', ascending=False) # '성능' 기준으로 내림차순 정렬
df.sort_values(['가격','성능'], ascending=False) # ['가격', '성능'] 순서대로 내림차순 정렬
성능 가격
BC1 70 20000
BC2 70 50000
BC3 90 50000
성능 가격
BC3 90 50000
BC1 70 20000
BC2 70 50000
성능 가격
BC3 90 50000
BC2 70 50000
BC1 70 10000
Pandas
행/열 합계
• df.sum( axis=? )
• axis는 1과 0 값 이며 입력하지 않으면 0로 자동 처리 (칼럼 기준 합)
• axis = 1로 입력시 각 열 기준으로 합산
df
df.sum() # 각 칼럼별 합계
성능 230
가격 120000
dtype: int64
df.sum(axis=1) # 각 로우별 합계
BC1 20070
BC2 50070
BC3 50090
dtype: int64
df['ROW_SUM'] = df.sum(axis=1) # 신규 칼럼 추가
df.loc['COL_SUM', :] = df.sum() # 신규 로우 추가
df
성능 가격 ROW_SUM
BC1 70 20000 20070
BC2 70 50000 50070
BC3 90 50000 50090
COL_SUM 230 120000 120230
성능 가격
BC1 70 20000
BC2 70 50000
BC3 90 50000
Pandas
시계열 시간 관리
• pd.to_datetime('문자열', format='입력된 문자열의 시간포멧')
• 문자열을 입력받아 Timestamp 객체로 변환. 파이썬 datetime 객체 변환 용이
• 시간포멧
기호 의미 자리수 출력
%Y 년 4 2018
%y 년 2 18
%m 월 2 09
%d 일 2 07
%H 시 (24시간) 2 17
%M 분 2 32
%S 초 2 58
%f 마이크로초 (1/10-6초) 6 004321
#문자열 입력을 받아서 Timestamp 객체로 변환
beg_time = pd.to_datetime('20180907 12:30:05', format='%Y%m%d %H:%M:%S')
end_time = pd.to_datetime('20180907 12:31:05', format='%Y%m%d %H:%M:%S')
Out[]: Timestamp('2018-09-07 12:30:05')
end_time - beg_time
Out[]: Timedelta('0 days 00:01:00')
Pandas
시계열 시간 관리
• pd.date_range('시작 일시 ', '종료 일시' , freq='빈도 포멧')
• 시작 일시와 종료 일시 사이에 빈도별 datetime 객체를 갖는 리스트 생성
• 빈도포멧 : {숫자}{기호}로 사용되며 숫자는 기호에 의미하는 기준 단위
#일자를 받아 월별 빈도 리스트
pd.date_range('20180101', '20180901', freq='M') #월말
Out[]: DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31', '2018-04-30'], dtype='datetime64[ns]', freq='M')
pd.date_range('20180101', '20180901', freq='MS') #월초
Out[]: DatetimeIndex(['2018-01-01', '2018-02-01', '2018-03-01', '2018-04-01', '2018-05-01'],
dtype='datetime64[ns]', freq='MS')
기호 의미
s 초
T 분
H 시간
D 일(day)
W 주(일요일)
W-MON 주(월요일)
M 각 달의 마지막 날
MS 각 달의 첫날
Pandas
시계열 시간 관리
• pd.date_range('시작 일시 ', '종료 일시' , freq='빈도 포멧')
• 시작 일시, 종료 일시 변수는 문자열, datetime 객체
• datetime 객체의 차를 구하려면 datetime.timedelta 함수를 사용
#현재 시점의 시간으로 부터 앞으로 5분 사이의 10초당 간격 리스트 추출
import datetime
import pandas as pd
beg_time = datetime.datetime.now() #현재시간 datetime 객체
end_time = datetime.datetime.now() + datetime.timedelta(minutes=5) #5분 이후 datetime 객체
pd.date_range(beg_time, end_time, freq='10s') #10초 간격으로 시간 리스트 구함
Out[]: DatetimeIndex(['2018-09-07 09:38:19.593836', '2018-09-07 09:38:29.593836',
'2018-09-07 09:38:39.593836', '2018-09-07 09:38:49.593836',
'2018-09-07 09:38:59.593836', '2018-09-07 09:39:09.593836',
.........
'2018-09-07 09:42:59.593836', '2018-09-07 09:43:09.593836',
'2018-09-07 09:43:19.593836'],
dtype='datetime64[ns]', freq='10S')
Pandas
DataFrame Merge
• 2개 DataFrame을 Join 하는 방법 : merge
• pd.merge( df1, df2, on=['KEY',…], how='inner')
• on = [ ]에 들어갈 값들은 병합 기준이 되는 칼럼명 (입력하지 않으면 동일 칼럼명들 지정)
• how = 'inner', 'left', 'right', 'outer' 중 선택 1개 (입력하지 않으면 inner로 지정 처리)
code = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']}
code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']}
tf = pd.DataFrame.from_dict(code)
vf = pd.DataFrame.from_dict(code2)
tf vf
pd.merge(tf, vf) # 동일 칼럼명인 CODE 기준으로 INNER JOIN 처리
CODE NAME
0 A 아
1 B 비
2 C 씨
3 D 디
4 E 이
CODE VALUE
0 A 1
1 B 2
2 C 3
3 X 4
4 Y 5
CODE NAME VALUE
0 A 아 1
1 B 비 2
2 C 씨 3
code1 = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']}
code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']}
df1 = pd.DataFrame.from_dict(code1)
df2 = pd.DataFrame.from_dict(code2)
rf = pd.merge(df1, df2, on=['CODE'], how='inner') # how를 지정하지 않아도 기본 inner로 동작
Pandas
Merge - Inner Join
• pd.merge( df1, df2, on=['CODE'], how='inner')
• 기준 칼럼에서 같은 값을 가진 열들의 요소들을 합친다.
• 기준 칼럼에서 같은 값이 아닌 대상들은 모두 제외된다.
CODE NAME
0 A 아
1 B 비
2 C 씨
3 D 디
4 E 이
CODE VALUE
0 A 1
1 B 2
2 C 3
3 X 4
4 Y 5
CODE NAME VALUE
0 A 아 1
1 B 비 2
2 C 씨 3
df1 df2
+ =
rf
code1 = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']}
code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']}
df1 = pd.DataFrame.from_dict(code1)
df2 = pd.DataFrame.from_dict(code2)
rf = pd.merge(df1, df2, on=['CODE'], how='left')
Pandas
Merge - Left Join
• pd.merge( df1, df2, on=['CODE'], how='left')
• 왼쪽 DataFrame의 다른 열 값들을 보존하며 오른쪽 DataFrame을 끼워 맞춘다.
• df1.CODE의 전체를 보존하며 병합, df2.CODE에서 없는 것들은 NaN으로 채움
CODE NAME
0 A 아
1 B 비
2 C 씨
3 D 디
4 E 이
CODE VALUE
0 A 1
1 B 2
2 C 3
3 X 4
4 Y 5
CODE NAME VALUE
0 A 아 1
1 B 비 2
2 C 씨 3
3 D 디 NaN
4 E 이 NaN
df1 df2
+ =
rf
code1 = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']}
code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']}
df1 = pd.DataFrame.from_dict(code1)
df2 = pd.DataFrame.from_dict(code2)
rf = pd.merge(df1, df2, on=['CODE'], how='right')
Pandas
Merge - Left Join
• pd.merge( df1, df2, on=['CODE'], how='right')
• 오른쪽 DataFrame의 다른 열 값들을 보존하며 왼쪽 DataFrame을 끼워 맞춘다.
• df2.CODE의 전체를 보존하며 병합, df1.CODE에서 없는 것들은 NaN으로 채움
CODE NAME
0 A 아
1 B 비
2 C 씨
3 D 디
4 E 이
CODE VALUE
0 A 1
1 B 2
2 C 3
3 X 4
4 Y 5
CODE NAME VALUE
0 A 아 1
1 B 비 2
2 C 씨 3
3 X NaN 4
4 Y NaN 5
df1 df2
+ =
rf
code1 = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']}
code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']}
df1 = pd.DataFrame.from_dict(code1)
df2 = pd.DataFrame.from_dict(code2)
rf = pd.merge(df1, df2, on=['CODE'], how='outer')
Pandas
Merge - Outer Join
• pd.merge( df1, df2, on=['CODE'], how='outer')
• 두 개의 DataFrame의 기준 칼럼의 합집합 기준으로 병합
• 서로 없는 CODE 값들에 해당되는 다른 칼럼들은 NaN으로 채움
CODE NAME
0 A 아
1 B 비
2 C 씨
3 D 디
4 E 이
CODE VALUE
0 A 1
1 B 2
2 C 3
3 X 4
4 Y 5
df1 df2
+ =
rf
CODE NAME VALUE
0 A 아 1
1 B 비 2
2 C 씨 3
3 D 디 NaN
4 E 이 NaN
5 X NaN 4
6 Y NaN 5
Pandas
그룹화 연산
• groupby(['칼럼명',…])
• '칼럼명' 내의 고유 값 기준으로 Groupby 객체 리턴
• 보통 groupby 메소드에 지정된 칼럼명은 인덱스로 지정됨
• Groupby 객체에는 그룹별로 연산을 할 수 있는 그룹 연산 메서드 존재
• Groupby 그룹 연산 메소드
• size(), count() : 갯수
• mean(), median(), min(), max() : 평균, 중앙값, 최소, 최대
• sum(), prod(), std(), var(), quantile() : 합계, 곱, 표준편차, 분산, 사분위수
df = pd.DataFrame(np.array([100,20000, 50,50000, 90, 50000]).reshape(3,2), columns=['성능','가격'])
df.groupby('성능').sum() df.groupby('성능').mean() df.groupby('성능').count()
가격
성능
70 70000
90 50000
가격
성능
70 35000
90 50000
가격
성능
70 2
90 1
4. 실전, 데이터분석
(1) 하루 승인 거래 건수 분석
• trns_1day_series 파일 : SEND, RECV, APPROVAL, REJECT 기준으로 1분당 거래 건수
• 거래 갭 건수, 거절율, 승인거래 회귀분석 데이터 분석
df = pd.read_csv('trns_1day_series')
df.head() #데이터 최초 5개 샘플 추출
df.describe() # 데이터 구성이 숫자일 때, DataFrame 구성 현황을 간략히 설명
SEND RECV APPROVAL REJECT
0 4779 5045 4024 755
1 5103 5055 4196 907
2 5035 5073 4653 382
3 4757 4762 4530 227
4 4639 4664 4425 214
SEND RECV APPROVAL REJECT
count 1440 1440 1440 1440
mean 10274.083 10274.832 10062.035 212.04792
std 6683.457 6683.4421 6584.3905 135.07823
min 769 769 714 16
25% 3580.75 3579.25 3469 84
50% 11115 11133.5 10901.5 210.5
75% 15745 15729.25 15451 305
max 24859 24911 24565 907
SEND,RECV,APPROVAL,REJECT
4779,5045,4024,755
5103,5055,4196,907
5035,5073,4653,382
4757,4762,4530,227
…..
trns_1day_series 내용
(1) 하루 승인 거래 건수 분석
# 24시간을 분으로 나누면 1440 구간
len(df)
Out[]: 1440
#1분 단위로 시간 리스트를 생성할 경우 1min
#1시간 단위로 시간 리스트 생성할 경우 1h
#1초 단위로 시간 리스트를 생성할 경우 1s
pd.date_range('00:00', '23:59', freq='1min')
Out[]: array([datetime.time(0, 0), datetime.time(0, 1), datetime.time(0, 2), ..., datetime.time(23, 57),
datetime.time(23, 58), datetime.time(23, 59)], dtype=object)
df['TIME'] = pd.date_range('00:00', '23:59', freq='1min')
df = df.set_index('TIME') # 인덱스로 지정
SEND RECV APPROVAL REJECT
TIME
0:00:00 4779 5045 4024 755
0:01:00 5103 5055 4196 907
0:02:00 5035 5073 4653 382
0:03:00 4757 4762 4530 227
0:04:00 4639 4664 4425 214
(1) 하루 승인 거래 건수 분석
# 거래 SEND, RECV 갭 차이
df['GAP'] = np.abs ( df.SEND - df.RECV )
df.plot(y='GAP') # df[['GAP']].plot() 결과는 동일
# 거래 거절율 계산
df['REJECT_AVG'] = df.REJECT / (df.APPROVAL + df.REJECT) * 100
df.plot(y='REJECT_AVG')
SEND RECV APPROVAL REJECT GAP REJECT_AVG
TIME
0:00:00 4779 5045 4024 755 266 15.798284
0:01:00 5103 5055 4196 907 48 17.773859
0:02:00 5035 5073 4653 382 38 7.586892
0:03:00 4757 4762 4530 227 5 4.771915
0:04:00 4639 4664 4425 214 25 4.613063
SEND RECV APPROVAL REJECT GAP
TIME
0:00:00 4779 5045 4024 755 266
0:01:00 5103 5055 4196 907 48
0:02:00 5035 5073 4653 382 38
0:03:00 4757 4762 4530 227 5
0:04:00 4639 4664 4425 214 25
(1) 하루 승인 거래 건수 분석
# 선형 회귀분석선 계산
len(df)
Out[]: 1440
np.arange(0, len(df))
Out[]: array([ 0, 1, 2, ..., 1437, 1438, 1439])
np.array(df.APPROVAL)
Out[]: array([4024, 4196, 4653, ..., 5006, 4935, 4940], dtype=int64)
fp = np.polyfit( np.arange(0, len(df)), np.array(df.APPROVAL), 8) # 8차 다항식 계수 추출
fd = np.poly1d(fp) # 다항식 함수 생성
df['REGRESSION'] = fd( np.arange(0, len(df)) ) # 회귀분석 데이터
df.plot(y=['APPROVAL','REGRESSION']) # 승인거래, 회귀분석선 출력
(1) 하루 승인 거래 건수 분석
회귀분석 평가 방법
# MSE 계산
((df.APPROVAL - df.REGRESSION) **2).sum() / 1440 # 오차의 제곱 (**2)을 합계(sum)을 낸 이후 나누기
Out[]: 2289273.5327607947
((df.APPROVAL - df.REGRESSION) **2).mean() # 오차 제곱에 대한 평균 함수
Out[]: 2289273.5327607947
# RMSE 계산
mse = ((df.APPROVAL - df.REGRESSION) **2).mean()
rmse = np.sqrt(mse)
rmse, mse
Out[]: (1513.0345444704144, 2289273.5327607947)
𝑦𝑡
𝑦𝑖
𝑦
𝑥
오차𝑒𝑖
손실함수(Loss function)
예상과 실측의 정답에 대한 오류를 하나의 숫자로 나타냄
정답에 가까우면 작은 값, 오답에 가까우면 큰 값
MSE(Mean Square Error) : 오차를 제곱한 것에 대한 평균
1
𝑛
෍
𝑖=1
(𝑦𝑖 − 𝑦𝑡)2
RMSE(Root Mean Square Error) : MSE에 제곱근
𝑀𝑆𝐸 =
1
𝑛
σ𝑖=1(𝑦𝑖 − 𝑦𝑡)2
(1) 하루 승인 거래 건수 분석
# 손실을 줄이기 위해 시간별 회귀분석선 재구현
# 1분당 거래이므로 60개 거래 실측값 * 24시간으로 2차원 배열 변환
hh_list = np.array( df.APPROVAL ).reshape(24, 60)
Out[]: array([[ 4024, 4196, 4653, ..., 3684, 3586, 3576],
[ 3507, 3689, 3542, ..., 2501, 2360, 2340],
[ 2058, 2010, 1858, ..., 1162, 1174, 1222],
...,
[13822, 13825, 13903, ..., 10940, 10827, 10839],
[10824, 10834, 10665, ..., 7589, 7378, 7470],
[ 7482, 7307, 7314, ..., 5006, 4935, 4940]], dtype=int64)
hh_list.shape
Out[]: (24, 60)
reg_list = []
for mm_list in hh_list: # 2차원 배열 리스트에 대한 배열 리스트 추출
x = np.arange(0, 60) # [0,…,59] 60개짜리 X축 배열 생성
y = mm_list # 60개짜리 실측값 Y축 배열 생성
fp = np.polyfit(x, y, 4) # 4차 다항식 계수 연산
fn = np.poly1d(fp) # 1차원 다항 함수 생성
reg_list.append(fn(x)) # 다항함수에 의한 회귀분석 데이터 생성
df['REGRESSION_H'] = np.array(reg_list).flatten() # 회귀분석 데이터를 1차원 리스트로 차원 축소 삽입
df.plot(y=['REGRESSION', 'REGRESSION_H']) # 기존 회귀분석, 신규 회귀분석 차트 출력
(2) 전문 거래 로그 분석
• 전문 거래들에 대한 로그들을 활용한 전문별 처리 시간 및 거래 현황 분석
• trns_msg_log 파일 : 전문에 대한 거래에 대한 로그
• {전송방향코드, 전문번호, 시간, 처리결과코드, 기관코드, 거래고유번호} 구성
• 데이터 구분자는 콜롬 (:)
• trns_firm_info 파일 : 기관코드별 기관명 (CSV 파일)
• trns_msg_info 파일 : 전문번호별 전문명 (CSV 파일)
• trns_msg_resp_code_info 파일 : 처리결과코드별 사유명 (CSV파일)
TRNS:MSG_CODE:TIME:RESP_CODE:FIRM_CODE:SEQ
1:0100:133000: :03:2e65c202e525e90e1d95
1:0300:133000: :48:802407d045fa5d1a8287
1:0200:133000: :03:a1d3e524e4751b450a20
1:0200:133000: :11:ed976e8de9708d167a64
1:9300:133000: :03:b7a878a4ff5d3076dd4b
1:0400:133000: :72:325d06919857f7f20761
1:0200:133000: :72:b07ecc97fbb154ac7373
2:9310:133000:00:20:ec1109dd984d711d4280
1:9300:133000: :20:ec1109dd984d711d4280
………
(2) 전문 거래 로그 분석
코드 데이터 정보 매핑
# 전문 로그 데이터 DataFrame으로 생성
log_df = pd.read_csv('trns_msg_log/trns_msg_log', sep=':', dtype=str)
# 전문코드 DataFrame생성, dtype을 지정한 이유는 전문번호를 숫자로 인식하여 0100이 100으로 변환되는 것을 막기 위함
msg_df = pd.read_csv('trns_msg_log/trns_msg_info', dtype=str)
TRNS MSG_CODE TIME RESP_CODE FIRM_CODE SEQ
0 1 0100 133000 03 2e65c202e525e90e1d95
1 1 0300 133000 48 802407d045fa5d1a8287
2 1 0200 133000 03 a1d3e524e4751b450a20
3 1 0200 133000 11 ed976e8de9708d167a64
4 1 9300 133000 03 b7a878a4ff5d3076dd4b
5 1 0400 133000 72 325d06919857f7f20761
6 1 0200 133000 72 b07ecc97fbb154ac7373
7 2 9310 133000 00 20 ec1109dd984d711d4280
8 1 9300 133000 20 ec1109dd984d711d4280
9 1 0420 133000 72 f24a35eca38fd37b698c
MSG_CODE MSG_NAME
0 0100 MS승인요청
1 0110 MS승인응답
2 0300 IC승인 요청
3 0310 IC승인 응답
4 0420 MS승인취소 요청
(2) 전문 거래 로그 분석
코드 데이터 정보 매핑
# 기관코드(FIRM_CODE)에 해당되는 정보 DataFrame 생성
firm_df = pd.read_csv('trns_msg_log/trns_firm_info', dtype=str)
# 응답코드(RESP_CODE)에 해당되는 정보 DataFrame 생성
resp_df = pd.read_csv('trns_msg_log/trns_msg_resp_code_info', dtype=str)
# 4개의 DataFrame 생성이 완료되었으면 본격적으로 데이터 전처리 시작
FIRM_CODE FIRM_NAME
0 03 IBK기업은행
1 11 NH농협은행
2 20 우리카드
3 23 SC제일은행
4 48 새마을금고
RESP_CODE RESP_NAME
0 00 정상
1 01 정상
2 60 거래정지카드
3 63 분실도난카드
4 K2 유효검증오류
5 Z1 시스템장애
(2) 전문 거래 로그 분석
코드 데이터 정보 매핑
# DataFrame Merge
tf1 = pd.merge(log_df, msg_df, on=['MSG_CODE'], how='left') # 전문번호 정보 병합
tf2 = pd.merge(tf1 , firm_df, on=['FIRM_CODE'], how='left') # 기관코드 정보 병합
tf3 = pd.merge(tf2 , resp_df, on=['RESP_CODE'], how='left') # 응답코드 정보 병합
# 송수신 구분자에 대한 변경
tf3.loc[tf3.TRNS == '1', 'TRNS'] = 'SEND' # tf3.TRNS=='1'인 열들을 모두 선택 후 TRNS 칼럼 값으로 'SEND'
tf3.loc[tf3.TRNS == '2', 'TRNS'] = 'RECV' # tr3.TRNS=='2'인 열들을 모두 선택 후 TRNS 칼럼 값으로 'RECV'
TRNS MSG_CODE TIME RESP_CODE FIRM_CODE SEQ MSG_NAME FIRM_NAME RESP_NAME
0 SEND 0100 133000 03 2e65c202e525e90e1d95 MS승인요청 IBK기업은행 NaN
1 SEND 0300 133000 48 802407d045fa5d1a8287 IC승인 요청 새마을금고 NaN
2 SEND 0200 133000 03 a1d3e524e4751b450a20 현금서비스 요청 IBK기업은행 NaN
3 SEND 0200 133000 11 ed976e8de9708d167a64 현금서비스 요청 NH농협은행 NaN
4 SEND 9300 133000 03 b7a878a4ff5d3076dd4b 기타승인 요청 IBK기업은행 NaN
5 SEND 0400 133000 72 325d06919857f7f20761 IC승인취소 요청 우체국 NaN
6 SEND 0200 133000 72 b07ecc97fbb154ac7373 현금서비스 요청 우체국 NaN
7 RECV 9310 133000 00 20 ec1109dd984d711d4280 기타승인 응답 우리카드 정상
8 SEND 9300 133000 20 ec1109dd984d711d4280 기타승인 요청 우리카드 NaN
9 SEND 0420 133000 72 f24a35eca38fd37b698c MS승인취소 요청 우체국 NaN
(2) 전문 거래 로그 분석
전문 처리시간 및 거래 현황
# 로그 거래 원본 데이터에서 SEND와 RECV 기준으로 두 개 DataFrame으로 분리
send_df = log_df[log_df.TRNS==1']
recv_df = log_df[log_df.TRNS =='2']
# 기관코드(FIRM_CODE)와 거래고유번호(SEQ)를 기준으로 병합
tf = pd.merge(send_df, recv_df, on=['FIRM_CODE', 'SEQ'], how='outer')
#필요한 칼럼만 필터링 후 해당 칼럼들에 대한 칼럼명 변경
tf = tf [['SEQ', 'FIRM_CODE', 'MSG_CODE_x', 'TIME_x', 'TIME_y','RESP_CODE_y']]
tf = tf.rename(columns={'MSG_CODE_x':'MSG_CODE', 'TIME_x':'SEND_TIME', 'TIME_y':'RECV_TIME',
'RESP_CODE_y':'RESP_CODE'})
TRNS_x MSG_CODE_x TIME_x RESP_CODE_x FIRM_CODE SEQ TRNS_y MSG_CODE_y TIME_y RESP_CODE_y
0 1 0100 133000 03 2e65c202e525e90e1d95 2 0110 133005 01
1 1 0300 133000 48 802407d045fa5d1a8287 2 0310 133001 01
2 1 0200 133000 03 a1d3e524e4751b450a20 2 0210 133000 01
3 1 0200 133000 11 ed976e8de9708d167a64 2 0210 133008 00
4 1 9300 133000 03 b7a878a4ff5d3076dd4b 2 9310 133003 01
SEQ FIRM_CODE MSG_CODE SEND_TIME RECV_TIME RESP_CODE
0 2e65c202e525e90e1d95 03 0100 133000 133005 01
1 802407d045fa5d1a8287 48 0300 133000 133001 01
2 a1d3e524e4751b450a20 03 0200 133000 133000 01
3 ed976e8de9708d167a64 11 0200 133000 133008 00
4 b7a878a4ff5d3076dd4b 03 9300 133000 133003 01
(2) 전문 거래 로그 분석
전문 처리시간 및 거래 현황
# 처리시간 계산
# SEND_TIME과 RECV_TIME은 문자열이므로 시간 GAP 계산을 위한 포멧 변환 필요
# pd.to_datetime 함수를 이용하면 쉽게 칼럼들에 대한 값을 datetime 객체들로 변환
tf['S_DATETIME'] = pd.to_datetime(tf.SEND_TIME, format='%H%M%S')
tf['R_DATETIME'] = pd.to_datetime(tf.RECV_TIME, format='%H%M%S')
tf['TIME_GAP'] = tf.R_DATETIME - tf.S_DATETIME
# 이제 불필요한 칼럼 제거
tf = tf.drop(['S_DATETIME','R_DATETIME'], axis=1)
SEQ FIRM_CODE MSG_CODE SEND_TIME RECV_TIME RESP_CODE TIME_GAP
0 2e65c202e525e90e1d95 03 0100 133000 133005 01 00:00:05
1 802407d045fa5d1a8287 48 0300 133000 133001 01 00:00:01
2 a1d3e524e4751b450a20 03 0200 133000 133000 01 00:00:00
3 ed976e8de9708d167a64 11 0200 133000 133008 00 00:00:08
4 b7a878a4ff5d3076dd4b 03 9300 133000 133003 01 00:00:03
5 325d06919857f7f20761 72 0400 133000 133002 01 00:00:02
6 b07ecc97fbb154ac7373 72 0200 133000 133008 00 00:00:08
7 ec1109dd984d711d4280 20 9300 133000 133000 00 00:00:00
8 f24a35eca38fd37b698c 72 0420 133000 133005 00 00:00:05
9 77b06c0cd73f42998019 11 9300 133000 133006 00 00:00:06
(2) 전문 거래 로그 분석
전문 처리시간 및 거래 현황
# 처리시간별 현황
tf.groupby('TIME_GAP').count() # 처리시간 그룹 후 칼럼별 ROW의 건수
tf.groupby('TIME_GAP').count().rename(columns={'SEQ':'COUNT'}) # 처리시간 그룹연산 처리 후 SEQ 칼럼명 변경
tf.groupby('TIME_GAP').count().rename(columns={'SEQ':'COUNT'}) [['COUNT']] # COUNT 칼럼만 선택
# 차트 출력
df = tf.groupby('TIME_GAP').count().rename(columns={'SEQ':'COUNT'}) [['COUNT']]
df.plot(kind='bar')
COUNT
TIME_GAP
0:00:00 91
0:00:01 96
0:00:02 112
0:00:03 96
0:00:04 99
0:00:05 106
0:00:06 99
0:00:07 94
0:00:08 104
0:00:09 103
(2) 전문 거래 로그 분석
전문 처리시간 및 거래 현황
#그룹화 칼럼을 2개로 지정했을 경우
# 기관코드, 전문번호 그룹화한 건수
tf.groupby(['FIRM_CODE','TIME_GAP']).count()
tf.groupby(['FIRM_CODE','TIME_GAP']).count().rename(columns={'SEQ':'COUNT'})
tf.groupby(['FIRM_CODE','TIME_GAP']).count().rename(columns={'SEQ':'COUNT'}) [['COUNT']]
df = tf.groupby(['FIRM_CODE', 'TIME_GAP']).count().rename(columns={'SEQ':'COUNT'}) [['COUNT']]
df.plot(kind='bar', figsize=(15,4)) #bar 차트, 차트의 크기는 (15, 4)
(2) 전문 거래 로그 분석
전문 처리시간 및 거래 현황
# 기관코드별 전분번호의 처리 시간 MAX, MIN (초) 분석
zf = tf[['FIRM_CODE','MSG_CODE','TIME_GAP']] # 3개 칼럼만 선택한 DataFrame 생성
max_df = zf.groupby(['FIRM_CODE','MSG_CODE']).max().rename(columns={'TIME_GAP':'MAX_GAP'})
min_df = zf.groupby(['FIRM_CODE','MSG_CODE']).min().rename(columns={'TIME_GAP':'MIN_GAP'})
max_df = max_df.reset_index() #그룹연산으로 지정된 index를 reset (merge를 위하여)
min_df = min_df.reset_index() #그룹연산으로 지정된 index를 reset
df = pd.merge(max_df, min_df)
df['MAX_GAP'] = df.MAX_GAP.dt.seconds # timedelta 객체를 seconds로 변환 (정수형 값)
df['MIN_GAP'] = df.MIN_GAP.dt.seconds # timedelta 객체를 seconds로 변환 (정수형 값)
df.set_index(['FIRM_CODE','MSG_CODE']).plot(kind='bar', figsize=(10,5)) # 차트 출력
5. 데이터 시각화
Matplotlib
기초 개념
• Matplotlib
• 산업계, 교육계에서 널리 사용되고 있는 수치 해석 소프트웨어
• 2차원 데이터를 시각화하기 위한 패키지
• MATLAB과 유사한 사용자 인터페이스
• 그래프의 종류, 축, 눈금선 그래프 이름 등 그림 요소의 상세한 서식 설정 가능
• 다양한 출력 형식(PNG,SVG,JPG 등)으로 저장 가능
%matplot inline
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
data = [0, 1]
ax.plot(data)
plt.show()
Matplotlib
Figure와 Subplot
• 핵심 개념 : Figure와 Subplot
Figure
Subplot (Axes) Subplot (Axes)
Figure 서브 플롯 (그래프영역) 작성 하는 틀
Subplot 그래프를 작성하기 위한 영역
Axes Figure 안의 (Sub)Plot들은 각각의 Axes 객체 속함
Axis 플롯의 가로 축이나 세로 축을 의미
Axis
Axis
Matplotlib
Figure와 Subplot
• add_subplot() 메소드
• add_subplot(지정위치 값)에서 지정위치 값은 3자리 숫자
• 지정위치 값은 순서대로 [총 행수], [총 열수], [서브플롯 번호] 의미
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(221) #2행 2열 1번
ax2 = fig.add_subplot(222) #2행 2열 2번
ax3 = fig.add_subplot(223) #2행 2열 3번
ax1.text(.2, .5, 'ax1(221)', fontsize=15)
ax2.text(.2, .5, 'ax2(222)', fontsize=15)
ax3.text(.2, .5, 'ax3(223)', fontsize=15)
plt.show()
Matplotlib
Figure와 Subplot
• add_subplot() 메소드
• add_subplot(지정위치 값)에서 지정위치의 3자리 숫자를 콤마(,)로 를 구분 가능
• add_subplot([총 행수], [총 열수], [서브플롯 번호]) 가능
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(2,2,1) #2행 2열 1번
ax2 = fig.add_subplot(2,2,2) #2행 2열 2번
ax3 = fig.add_subplot(2,2,3) #2행 2열 3번
ax1.plot([0,1]) # Y축값 (0, 1)
ax2.plot([1,0]) # Y축값 (1, 0)
ax3.plot([1,1]) # Y축값 (1, 1)
plt.show()
Matplotlib
Figure와 Subplot
• subplots() 메소드
• pyplot.subplots() 메소드를 이용해 Figure 생성과 Subplot 배치를 동시 설정
• pyplot.subplots() 메소드의 리턴 값은 figure와 axes 객체 배열
• axes[열 인덱스, 행 인덱스]
• 인덱스는 0부터 시작하는 점을 참고
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 2) #2x2 Axes 배열 생성
axes[0, 0].plot([0,1]) # Y축값 (0, 1)
axes[0, 1].plot([1,0]) # Y축값 (1, 0)
axes[1, 0].plot([1,1]) # Y축값 (1, 1)
plt.show()
Matplotlib
꺾은선 그래프
• Axes.plot([x], y, [fmt], data=None, **kwargs) 메소드
• plot() 메소드의 파라미터가 하나일 경우 Y 값으로 설정되고, X 값은 자동적으로 지정
• plot() 메소드에 사용되는 데이터형
• 파이썬 기본 1차원 구조체(리스트, 튜플)
• numpy.ndarray
• pandas.Series
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x = [0, 2, 4]
y = [0, 4, 2]
ax.plot(x, y)
plt.show()
Matplotlib
꺾은선 그래프
• 여러 개의 선을 그리는 경우
• 1개의 서브플롯에 여러 개의 그래프를 그릴 수 있음
• Axes 객체에 plot()을 여러 번 호출
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x = [0, 1, 2]
y1 = [0, 4, 3]
y2 = [3, 2, 0]
ax.plot(x, y1)
ax.plot(x, y2)
plt.show()
Matplotlib
꺾은선 그래프
• 하루치 거래 승인 꺾은선 그래프
• pandas의 Series를 지정하여 그리기
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('trns_1day_series')
fig = plt.figure(figsize=(10, 4)) # 그래프 크기
ax = fig.add_subplot(111)
ax.plot(df.index, df.APPROVAL, label='승인') # 승인건수
ax.plot(df.index, df.REJECT , label='거절') # 거절건수
ax.set_title('1일 거래 건수 현황') # 차트 타이틀
ax.set_ylabel('건수') # Y축 레이블
ax.set_xlabel('시간') # X축 레이블
#범례 유호화
ax.legend()
plt.show()
Matplotlib
차트 한글 폰트 지정
• 맑은 고딕체 폰트 확인
from matplotlib import rcParams
rcParams['font.sans-serif']= 'Malgun Gothic'
rcParams['font.weight'] = 'regular'
rcParams['axes.titlesize'] = 15
rcParams['ytick.labelsize'] = 12
rcParams['xtick.labelsize'] = 12
import matplotlib.font_manager as fm
font_list = fm.findSystemFonts(fontpaths=None, fontext='ttf')
[(f.name, f.fname) for f in fm.fontManager.ttflist if 'Malgun' in f.name]
Out[]: [('Malgun Gothic', 'C:WindowsFontsmalgun.ttf'),
('Malgun Gothic', 'C:WindowsFontsmalgunsl.ttf'),
('Malgun Gothic', 'C:WindowsFontsmalgunbd.ttf')]
• 맑은 고딕체 폰트 지정
Matplotlib
꺾은선 그래프
• 그래프 스타일 적용 옵션
• linestyle = solid, dashed, dotted, dashdotted 등 그래프 선의 형태
• color = black, grey, red, blue 등 그래프의 색깔
• marker = o , >, ^ 등 좌표에 해당하는 값 부분을 표시하는 마커
color linestyle
Matplotlib
꺾은선 그래프
• 그래프 스타일 적용
• color = 'r' 대표 16색에 대해서는 앞글자 1개만 지정해도 됨
• linestyle = 'dashed' 선의 스타일을 결정
• marker = 'o' 마커의 타입을 결정
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x = [0, 1, 2]
y1 = [0, 4, 3]
y2 = [3, 2, 0]
ax.plot(x, y1, color='g', linestyle='dashed', marker='o')
ax.plot(x, y2, color='r', linestyle='dotted', marker='^')
plt.show()
Matplotlib
꺾은선 그래프
• 하루치 거래 승인 꺾은선 그래프
• 선 그래프의 스타일 적용
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('trns_1day_series')
fig = plt.figure(figsize=(10, 4))
ax = fig.add_subplot(111)
ax.plot(df.index, df.APPROVAL, label='승인', linestyle='dotted', c='g') # 승인건수
ax.plot(df.index, df.REJECT , label='거절', linestyle='dashed', c='r') # 거절건수
ax.set_title('1일 거래 건수 현황') # 차트 타이틀
ax.set_ylabel('건수') # Y축 레이블
ax.set_xlabel('시간') # X축 레이블
#범례 유호화
ax.legend()
plt.show()
Matplotlib
막대 그래프
• Axes.bar(*args, data=None, **kwargs) 메소드
• 막대 그래프는 수량을 막대의 길이로 나타낸 그래프
• 파라미터로 X, Y 값을 지정
• tick_label = [] 에서 배열 인자로 눈금에 대한 레이블 지정 가능
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x = [1, 2]
y = [3, 5]
labels = ['A', 'B']
ax.bar(x, y, tick_label=labels)
plt.show()
Matplotlib
막대 그래프
• Axes.barh(*args, data=None, **kwargs) 메소드
• 막대 그래프를 수평으로 나타내도록 한다.
• 입력 값은 bar() 메소드와 동일
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x = [1, 2]
y = [3, 5]
labels = ['A', 'B']
ax.barh(x, y, tick_label=labels)
plt.show()
Matplotlib
막대 그래프
• 실패한 막대 그래프의 그룹화
• 여러 번의 Axes.bar(x, y) 호출에서 X 좌표 위치가 동일할 경우 덮어 씌워짐
• BAR 차트에서 데이터 그룹화를 위해서는 표현을 위한 전략 필요
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('trns_1day_series')
df.mean()
Out[]: SEND 10274.082639
RECV 10274.831944
APPROVAL 10062.034722
REJECT 212.047917
dtype: float64
s_mean, s_max = df.mean() , df.max()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar([1,2,3,4], s_mean, label='평균') #X축 좌표 = [1,2,3,4]
ax.bar([1,2,3,4], s_max , label='최대') #X축 좌표 = [1,2,3,4]
plt.show()
Matplotlib
막대 그래프
• 데이터를 각각 표현하는 방법
• '평균' 데이터들의 좌표를 1씩 공간을 만들고, 그 사이에 '최대' 데이터들을 위치
• '평균' 데이터들의 X좌표 = [1,3,5,7]
• '최대' 데이터들의 X좌표 = [2,4,6,8]
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('trns_1day_series')
s_mean, s_max = df.mean() , df.max()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar([1,3,5,7], s_mean, label='평균')
ax.bar([2,4,6,8], s_max, label='최대')
ax.legend()
plt.show()
서로 X 축의 좌표를 침범하지 않게 한다
Matplotlib
막대 그래프
• 같은 인덱스는 붙이고, 다른 인덱스는 멀리.
• 두 '평균' 데이터, '최대' 데이터의 X좌표는 각각 1, 2부터 시작
• 차트 폭(width)을 1로 지정하여 '평균'과 '최대' 그래프를 붙임
• 각각의 X좌표는 3씩 증가시키면 인덱스별 분류가 좀더 쉽게 인식
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('trns_1day_series')
s_mean, s_max = df.mean() , df.max()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar([1,4,7,10], s_mean, width=1, label='평균')
ax.bar([2,5,8,11], s_max, width=1, label='최대')
ax.legend()
plt.show()
남은 문제 - 레이블을 카테고리화를 시켜야 한다.
Matplotlib
막대 그래프
• X 축의 레이블 표시 기준 변경
• 각 데이터셋은 4가지 데이터 기준으로 표현 (SEND, RECV, APPROVAL, REJECT)
• X좌표에 분류된 데이터 중심 값을 4개 지정하여 표시
• set_xticks([X축 값1, X축 값2,…,… ]) : 여기에 지정된 X축 값만 레이블로 나타남
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('trns_1day_series')
s_mean, s_max = df.mean() , df.max()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar([1,3,5,7], s_mean, label='평균')
ax.bar([2,4,6,8], s_max, label='최대')
ax.set_xticks([1.5, 4.5, 7, 11])
ax.legend()
plt.show()
Matplotlib
막대 그래프
• X좌표의 레이블 카테고리 값 지정
• X좌표의 tick 값을 숫자가 아닌 카테고리 지정 값으로 변경
• set_xticklabels([카테고리 값1, 카테고리 값2, …, ])
• set_xticks() 메소드가 먼저 호출된 이후 지정되어야 함
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('trns_1day_series')
s_mean, s_max = df.mean() , df.max()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar([1,3,5,7], s_mean, label='평균')
ax.bar([2,4,6,8], s_max, label='최대')
ax.set_xticks([1.5, 4.5, 7, 11])
ax.set_xticklabels(['SEND','RECV','APPROVAL','REJECT'])
ax.legend()
plt.show()
Matplotlib
두 개 축을 가진 그래프
• 두 개의 Y축 기준을 나타내는 그래프
• Y 축을 LEFT 사이드와 RIGHT 사이드로 2개 축 지정
• twinx() : X 축의 기준을 공유하여 2개 Y축을 가질 경우
• twiny() : Y 축의 기준을 공유하여 2개 X축을 가질 경우
fig = plt.figure(figsize=(10, 4))
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx() # X축 공유하는 Y축 분리
ax1.plot(df.index, df.APPROVAL, label='승인', color='green')
ax2.bar(df.index, df.REJECT , label='거절', color='purple' )
ax1.set_title('1일 거래 건수 현황')
ax1.set_ylabel('승인 건수') #Y1축 레이블
ax2.set_ylabel('거절 건수') #Y2축 레이블
ax1.set_xlabel('시간')
ax1.legend(loc=2) #범례 위치 지정
ax2.legend(loc=1) #범례 위치 지정
plt.show()
Matplotlib
산점도 그래프
• 점(scatter) 그래프
• Axes.scatter(x, y, …) 메소드 사용
• X축과 Y축에 수량이나 크기 등을 표시하기 위해 적합
• 일반적으로 데이터 분포 상황을 확인할 때 많이 활용
fig = plt.figure(figsize=(10, 4))
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx() # X축 공유하는 Y축 분리
ax1.plot(df.index, df.APPROVAL, label='승인', color='green')
ax2.scatter(df.index, df.REJECT , label='거절', color='purple' )
ax1.set_title('1일 거래 건수 현황')
ax1.set_ylabel('승인 건수') #Y1축 레이블
ax2.set_ylabel('거절 건수') #Y2축 레이블
ax1.set_xlabel('시간')
ax1.legend(loc=2) #범례 위치 지정
ax2.legend(loc=1) #범례 위치 지정
plt.show()
Matplotlib
원 그래프
• 원(circle) 그래프
• Axes.pie(x, labels=[], …) 메소드 사용
• 배열 X는 필수, labels 와 같은 옵션들에 의해 스타일이 결정
from matplotlib import rcParams
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
rcParams['font.sans-serif']= 'Malgun Gothic'
rcParams['font.weight'] = 'regular'
rcParams['axes.titlesize'] = 15
rcParams['ytick.labelsize'] = 12
rcParams['xtick.labelsize'] = 12
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111)
label_list = ['승인','입금','제휴']
dataset = [50, 100, 30]
ax.pie(dataset, labels=label_list)
plt.show()
Seaborn
기초 개념
• 시각화와 통계 기능을 보다 편리하게 제공
• 시각화 기능은 Matplotlib 패키지를 기반으로 개발되어 편리한 시각화 기능
• 통계적 기능은 Statsmodel 패키지를 기반으로 개발되어 편리한 분석 기능
• 샘플 데이터를 제공하여 교육용 데이터가 풍부하게 제공
• 단순 그래프부터 히트맵까지 다양한 시각화 기능 제공함
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
df = pd.read_csv('trns_1day_series') df.describe()
sns.boxplot(data=df) #박스플롯으로 표시
SEND RECV APPROVAL REJECT
count 1440 1440 1440 1440
mean 10274.083 10274.832 10062.035 212.04792
std 6683.457 6683.4421 6584.3905 135.07823
min 769 769 714 16
25% 3580.75 3579.25 3469 84
50% 11115 11133.5 10901.5 210.5
75% 15745 15729.25 15451 305
max 24859 24911 24565 907
Seaborn
박스 플롯
• 카테고리 기준으로 데이터 변화를 표현할 때 유리
• 표현할 때는 카테고리를 명확하게 구분 지어야 함
• 어떤 기준으로 데이터의 수치를 표현할지!
• 카테고리 기준은 hue 옵션에 지정하면 됨 (hue 사용 시 X축, Y축 기준은 필수)
df = pd.read_csv('titanic.csv', sep='t')
df.head()
sns.boxplot(x='Survived', y='Age', hue='Sex', data=df) #성별 기준으로, 생존여부 기준으로 나이 분포
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S
4 5 0 3 Allen, Mr. William Henry male 35 0 0 373450 8.05 NaN S
Seaborn
박스 플롯
#기관코드별 정상(APPROVAL)/거절(REJECT) 처리시간 분포 시각화
df = pd.read_csv('trns_msg_log/trns_msg_log', sep=':', dtype=str) #거래 로그 DataFrame
s_df = df[df.TRNS == '1'] #SEND 거래
r_df = df[df.TRNS == '2'] #RECV 거래
tf = pd.merge(s_df, r_df, on=['FIRM_CODE','SEQ'])
tf['APPROVAL'] = tf.RESP_CODE_y.isin(['00','01']) #정상 여부
# SEND와 RECV 전문 처리시간
tf['S_DATETIME'] = pd.to_datetime(tf.TIME_x, format='%H%M%S')
tf['R_DATETIME'] = pd.to_datetime(tf.TIME_y, format='%H%M%S')
tf['TIME_GAP'] = tf.R_DATETIME - tf.S_DATETIME
tf['TIME_GAP'] = tf.TIME_GAP.dt.seconds #시간을 초 단위 정수로 변환
#승인/거절 카테고리 기준으로, 기관별 처리시간 분포
sns.boxplot(x='FIRM_CODE', y='TIME_GAP', hue='APPROVAL', data=tf)
Seaborn
박스 플롯
• 카테고리 기준으로 데이터 변화를 표현할 때 유리
• 표현할 때는 카테고리를 명확하게 구분 지어야 함
• 어떤 기준으로 데이터의 수치를 표현할지!
• 카테고리 기준은 hue 옵션에 지정하면 됨 (hue 사용 시 X축, Y축 기준은 필수)
df = pd.read_csv('titanic.csv', sep='t')
df.head()
sns.boxplot(x='Survived', y='Age', hue='Sex', data=df) #성별 기준으로, 생존여부 기준으로 나이 분포
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S
4 5 0 3 Allen, Mr. William Henry male 35 0 0 373450 8.05 NaN S
Seaborn
회귀분석 그래프
• lmplot() 메소드를 이용하여 회귀분석 판별
• hue 옵션 사용을 통해 기준을 세분화 하여 시각화 가능
df = pd.read_csv('titanic.csv', sep='t')
sns.lmplot(x='Age',y='Fare', data=df) #나이별 운임료 회귀분석
sns.lmplot(x='Age',y='Fare', hue='Survived', data=df) #생존여부 기준으로 나이별 운임료 회귀분석
Seaborn
회귀분석 그래프
• tips 데이터셋을 이용하여 전체 지불금액(total_bill)과 팁(tip) 상관관계 분석
df = sns.load_dataset('tips')
df.head()
#생별 기준으로 전체 지불금액과 팀의 상관관계 회귀분석
sns.lmplot(x='total_bill', y='tip', hue='sex', data=df) hue ='smoker'로 했을 경우
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.5 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
Seaborn
히트맵(Heatmap)
• 두 개의 카테고리에 해당되는 값의 변화와 분포를 나타낼 때 유리
• DataFrame에서 인덱스와 칼럼이 카테고리 값이 됨
• DataFrame 이용 시 pivot(index, columns, values) 메소드를 이용하여 변조 필요
df = pd.read_csv('titanic.csv', sep='t')
#생존자 기준으로 Age, Sex, Fare를 그룹화하여 건수를 추출
tf = df[df.Survived==1].groupby(['Age','Sex','Fare']).count().reset_index()
tf = tf[['Age','Sex','Fare','Pclass']]
tf = tf.rename(columns={'Pclass':'Count'})
zf = tf.pivot('Age','Fare', 'Count').fillna(0)
sns.heatmap(zf) # 연령, 운임에 따른 승객수 현황
Age Sex Fare Count
0 0.83 male 29 1
1 3 female 41.5792 1
2 4 female 16.7 1
3 5 female 27.75 1
4 12 male 11.2417 1
Seaborn
히트맵(Heatmap)
• df.pivot()의 경우 중복이나 값이 없을 때 아래 에러가 발생
ValueError: Index contains duplicate entries, cannot reshape
• pd.pivot_table의 경우는 index의 중복이 있어도 해결 가능
• pd.pivot_table의 경우 aggfunc 옵션이 제공되어 np.sum, np.mean 등 그룹함수 사용 가능
df = pd.read_csv('titanic.csv', sep='t')
tf = df.groupby(['Age','Sex','Survived']).count().reset_index().rename(columns={'Pclass':'Count'})
tf = tf[['Age','Sex','Survived','Count']]
# 좌측 인덱스가 Age(연령), 상단 칼럼은 Survived(생존여부)로 한 사람수를 나타내는 DataFrame으로 변조
zf = pd.pivot_table(tf,index='Age',columns='Survived',values='Count', aggfunc=np.sum).fillna(0)
sns.heatmap(zf)
pd.pivot_table(index='Sex', columns='Survived', values='Count', aggfunc=np.sum)
Q&A

More Related Content

What's hot

파이썬을 활용한 챗봇 서비스 개발 3일차
파이썬을 활용한 챗봇 서비스 개발 3일차파이썬을 활용한 챗봇 서비스 개발 3일차
파이썬을 활용한 챗봇 서비스 개발 3일차Taekyung Han
 
敵対的学習に対するラデマッハ複雑度
敵対的学習に対するラデマッハ複雑度敵対的学習に対するラデマッハ複雑度
敵対的学習に対するラデマッハ複雑度Masa Kato
 
딥러닝 기본 원리의 이해
딥러닝 기본 원리의 이해딥러닝 기본 원리의 이해
딥러닝 기본 원리의 이해Hee Won Park
 
Python基礎その1
Python基礎その1Python基礎その1
Python基礎その1大貴 末廣
 
スパース性に基づく機械学習 2章 データからの学習
スパース性に基づく機械学習 2章 データからの学習スパース性に基づく機械学習 2章 データからの学習
スパース性に基づく機械学習 2章 データからの学習hagino 3000
 
スマートフォン向けサービスにおけるサーバサイド設計入門
スマートフォン向けサービスにおけるサーバサイド設計入門スマートフォン向けサービスにおけるサーバサイド設計入門
スマートフォン向けサービスにおけるサーバサイド設計入門Hisashi HATAKEYAMA
 
Deepcheck, 딥러닝 기반의 얼굴인식 출석체크
Deepcheck, 딥러닝 기반의 얼굴인식 출석체크Deepcheck, 딥러닝 기반의 얼굴인식 출석체크
Deepcheck, 딥러닝 기반의 얼굴인식 출석체크지운 배
 
Rで計量時系列分析~CRANパッケージ総ざらい~
Rで計量時系列分析~CRANパッケージ総ざらい~ Rで計量時系列分析~CRANパッケージ総ざらい~
Rで計量時系列分析~CRANパッケージ総ざらい~ Takashi J OZAKI
 
Multiple optimization and Non-dominated sorting with rPref package in R
Multiple optimization and Non-dominated sorting with rPref package in RMultiple optimization and Non-dominated sorting with rPref package in R
Multiple optimization and Non-dominated sorting with rPref package in RSatoshi Kato
 
pythonワンライナーのすゝめ
pythonワンライナーのすゝめpythonワンライナーのすゝめ
pythonワンライナーのすゝめcocu_628496
 
Djangoのエントリポイントとアプリケーションの仕組み
Djangoのエントリポイントとアプリケーションの仕組みDjangoのエントリポイントとアプリケーションの仕組み
Djangoのエントリポイントとアプリケーションの仕組みShinya Okano
 
並行プログラミングと継続モナド
並行プログラミングと継続モナド並行プログラミングと継続モナド
並行プログラミングと継続モナドKousuke Ruichi
 
Elasticsearch: Introducing the wildcard field
Elasticsearch: Introducing the wildcard fieldElasticsearch: Introducing the wildcard field
Elasticsearch: Introducing the wildcard fieldElasticsearch
 
기계학습 / 딥러닝이란 무엇인가
기계학습 / 딥러닝이란 무엇인가기계학습 / 딥러닝이란 무엇인가
기계학습 / 딥러닝이란 무엇인가Yongha Kim
 
遺伝的アルゴリズム (Genetic Algorithm)を始めよう!
遺伝的アルゴリズム(Genetic Algorithm)を始めよう!遺伝的アルゴリズム(Genetic Algorithm)を始めよう!
遺伝的アルゴリズム (Genetic Algorithm)を始めよう!Kazuhide Okamura
 
scikit-learnを用いた機械学習チュートリアル
scikit-learnを用いた機械学習チュートリアルscikit-learnを用いた機械学習チュートリアル
scikit-learnを用いた機械学習チュートリアル敦志 金谷
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 Yong Joon Moon
 
Graphic Notes on Linear Algebra and Data Science
Graphic Notes on Linear Algebra and Data ScienceGraphic Notes on Linear Algebra and Data Science
Graphic Notes on Linear Algebra and Data ScienceKenji Hiranabe
 
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기강 민우
 
Django ORM道場:クエリの基本を押さえ,より良い形を身に付けよう
Django ORM道場:クエリの基本を押さえ,より良い形を身に付けようDjango ORM道場:クエリの基本を押さえ,より良い形を身に付けよう
Django ORM道場:クエリの基本を押さえ,より良い形を身に付けようTakayuki Shimizukawa
 

What's hot (20)

파이썬을 활용한 챗봇 서비스 개발 3일차
파이썬을 활용한 챗봇 서비스 개발 3일차파이썬을 활용한 챗봇 서비스 개발 3일차
파이썬을 활용한 챗봇 서비스 개발 3일차
 
敵対的学習に対するラデマッハ複雑度
敵対的学習に対するラデマッハ複雑度敵対的学習に対するラデマッハ複雑度
敵対的学習に対するラデマッハ複雑度
 
딥러닝 기본 원리의 이해
딥러닝 기본 원리의 이해딥러닝 기본 원리의 이해
딥러닝 기본 원리의 이해
 
Python基礎その1
Python基礎その1Python基礎その1
Python基礎その1
 
スパース性に基づく機械学習 2章 データからの学習
スパース性に基づく機械学習 2章 データからの学習スパース性に基づく機械学習 2章 データからの学習
スパース性に基づく機械学習 2章 データからの学習
 
スマートフォン向けサービスにおけるサーバサイド設計入門
スマートフォン向けサービスにおけるサーバサイド設計入門スマートフォン向けサービスにおけるサーバサイド設計入門
スマートフォン向けサービスにおけるサーバサイド設計入門
 
Deepcheck, 딥러닝 기반의 얼굴인식 출석체크
Deepcheck, 딥러닝 기반의 얼굴인식 출석체크Deepcheck, 딥러닝 기반의 얼굴인식 출석체크
Deepcheck, 딥러닝 기반의 얼굴인식 출석체크
 
Rで計量時系列分析~CRANパッケージ総ざらい~
Rで計量時系列分析~CRANパッケージ総ざらい~ Rで計量時系列分析~CRANパッケージ総ざらい~
Rで計量時系列分析~CRANパッケージ総ざらい~
 
Multiple optimization and Non-dominated sorting with rPref package in R
Multiple optimization and Non-dominated sorting with rPref package in RMultiple optimization and Non-dominated sorting with rPref package in R
Multiple optimization and Non-dominated sorting with rPref package in R
 
pythonワンライナーのすゝめ
pythonワンライナーのすゝめpythonワンライナーのすゝめ
pythonワンライナーのすゝめ
 
Djangoのエントリポイントとアプリケーションの仕組み
Djangoのエントリポイントとアプリケーションの仕組みDjangoのエントリポイントとアプリケーションの仕組み
Djangoのエントリポイントとアプリケーションの仕組み
 
並行プログラミングと継続モナド
並行プログラミングと継続モナド並行プログラミングと継続モナド
並行プログラミングと継続モナド
 
Elasticsearch: Introducing the wildcard field
Elasticsearch: Introducing the wildcard fieldElasticsearch: Introducing the wildcard field
Elasticsearch: Introducing the wildcard field
 
기계학습 / 딥러닝이란 무엇인가
기계학습 / 딥러닝이란 무엇인가기계학습 / 딥러닝이란 무엇인가
기계학습 / 딥러닝이란 무엇인가
 
遺伝的アルゴリズム (Genetic Algorithm)を始めよう!
遺伝的アルゴリズム(Genetic Algorithm)を始めよう!遺伝的アルゴリズム(Genetic Algorithm)を始めよう!
遺伝的アルゴリズム (Genetic Algorithm)を始めよう!
 
scikit-learnを用いた機械学習チュートリアル
scikit-learnを用いた機械学習チュートリアルscikit-learnを用いた機械学習チュートリアル
scikit-learnを用いた機械学習チュートリアル
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
 
Graphic Notes on Linear Algebra and Data Science
Graphic Notes on Linear Algebra and Data ScienceGraphic Notes on Linear Algebra and Data Science
Graphic Notes on Linear Algebra and Data Science
 
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
 
Django ORM道場:クエリの基本を押さえ,より良い形を身に付けよう
Django ORM道場:クエリの基本を押さえ,より良い形を身に付けようDjango ORM道場:クエリの基本を押さえ,より良い形を身に付けよう
Django ORM道場:クエリの基本を押さえ,より良い形を身に付けよう
 

Similar to 파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)

파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) 파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) Tae Young Lee
 
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영Tae Young Lee
 
20150306 파이썬기초 IPython을이용한프로그래밍_이태영
20150306 파이썬기초 IPython을이용한프로그래밍_이태영20150306 파이썬기초 IPython을이용한프로그래밍_이태영
20150306 파이썬기초 IPython을이용한프로그래밍_이태영Tae Young Lee
 
Lecture 1: Introduction to Python and TensorFlow
Lecture 1: Introduction to Python and TensorFlowLecture 1: Introduction to Python and TensorFlow
Lecture 1: Introduction to Python and TensorFlowSang Jun Lee
 
머신러닝 및 데이터 과학 연구자를 위한 python 기반 컨테이너 분산처리 플랫폼 설계 및 개발
머신러닝 및 데이터 과학 연구자를 위한 python 기반 컨테이너 분산처리 플랫폼 설계 및 개발머신러닝 및 데이터 과학 연구자를 위한 python 기반 컨테이너 분산처리 플랫폼 설계 및 개발
머신러닝 및 데이터 과학 연구자를 위한 python 기반 컨테이너 분산처리 플랫폼 설계 및 개발Jeongkyu Shin
 
[NDC12] 변화량 분석을 중심으로 한 저비용 고효율의 지속가능한 코드퀄리티 관리법 - 송창규
[NDC12] 변화량 분석을 중심으로 한 저비용 고효율의 지속가능한 코드퀄리티 관리법 - 송창규[NDC12] 변화량 분석을 중심으로 한 저비용 고효율의 지속가능한 코드퀄리티 관리법 - 송창규
[NDC12] 변화량 분석을 중심으로 한 저비용 고효율의 지속가능한 코드퀄리티 관리법 - 송창규ChangKyu Song
 
Python 생태계의 이해
Python 생태계의 이해Python 생태계의 이해
Python 생태계의 이해용 최
 
Python 활용: 이미지 처리와 데이터 분석
Python 활용: 이미지 처리와 데이터 분석Python 활용: 이미지 처리와 데이터 분석
Python 활용: 이미지 처리와 데이터 분석용 최
 
[온라인교육시리즈] Jupyter를 이용한 분석 환경 구축하기 - 허창현 클라우드 솔루션 아키텍트
[온라인교육시리즈] Jupyter를 이용한 분석 환경 구축하기 - 허창현 클라우드 솔루션 아키텍트[온라인교육시리즈] Jupyter를 이용한 분석 환경 구축하기 - 허창현 클라우드 솔루션 아키텍트
[온라인교육시리즈] Jupyter를 이용한 분석 환경 구축하기 - 허창현 클라우드 솔루션 아키텍트NAVER CLOUD PLATFORMㅣ네이버 클라우드 플랫폼
 
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅Youngmin Koo
 
Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...
Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...
Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...hoondong kim
 
Boost 라이브리와 C++11
Boost 라이브리와 C++11Boost 라이브리와 C++11
Boost 라이브리와 C++11OnGameServer
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기Jaeseung Ha
 
eclipse에서 intelliJ IDEA로
eclipse에서 intelliJ IDEA로eclipse에서 intelliJ IDEA로
eclipse에서 intelliJ IDEA로Juntai Park
 
PyQGIS와 PyQt를 이용한 QGIS 기능 확장
PyQGIS와 PyQt를 이용한 QGIS 기능 확장PyQGIS와 PyQt를 이용한 QGIS 기능 확장
PyQGIS와 PyQt를 이용한 QGIS 기능 확장MinPa Lee
 

Similar to 파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영) (20)

파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) 파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
 
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
 
20150306 파이썬기초 IPython을이용한프로그래밍_이태영
20150306 파이썬기초 IPython을이용한프로그래밍_이태영20150306 파이썬기초 IPython을이용한프로그래밍_이태영
20150306 파이썬기초 IPython을이용한프로그래밍_이태영
 
JetsonTX2 Python
 JetsonTX2 Python  JetsonTX2 Python
JetsonTX2 Python
 
파이썬으로 익히는 딥러닝
파이썬으로 익히는 딥러닝파이썬으로 익히는 딥러닝
파이썬으로 익히는 딥러닝
 
파이썬 데이터 분석 (18년)
파이썬 데이터 분석 (18년)파이썬 데이터 분석 (18년)
파이썬 데이터 분석 (18년)
 
Lecture 1: Introduction to Python and TensorFlow
Lecture 1: Introduction to Python and TensorFlowLecture 1: Introduction to Python and TensorFlow
Lecture 1: Introduction to Python and TensorFlow
 
파이선 실전공략-1
파이선 실전공략-1파이선 실전공략-1
파이선 실전공략-1
 
머신러닝 및 데이터 과학 연구자를 위한 python 기반 컨테이너 분산처리 플랫폼 설계 및 개발
머신러닝 및 데이터 과학 연구자를 위한 python 기반 컨테이너 분산처리 플랫폼 설계 및 개발머신러닝 및 데이터 과학 연구자를 위한 python 기반 컨테이너 분산처리 플랫폼 설계 및 개발
머신러닝 및 데이터 과학 연구자를 위한 python 기반 컨테이너 분산처리 플랫폼 설계 및 개발
 
[NDC12] 변화량 분석을 중심으로 한 저비용 고효율의 지속가능한 코드퀄리티 관리법 - 송창규
[NDC12] 변화량 분석을 중심으로 한 저비용 고효율의 지속가능한 코드퀄리티 관리법 - 송창규[NDC12] 변화량 분석을 중심으로 한 저비용 고효율의 지속가능한 코드퀄리티 관리법 - 송창규
[NDC12] 변화량 분석을 중심으로 한 저비용 고효율의 지속가능한 코드퀄리티 관리법 - 송창규
 
Python 생태계의 이해
Python 생태계의 이해Python 생태계의 이해
Python 생태계의 이해
 
Python 활용: 이미지 처리와 데이터 분석
Python 활용: 이미지 처리와 데이터 분석Python 활용: 이미지 처리와 데이터 분석
Python 활용: 이미지 처리와 데이터 분석
 
[온라인교육시리즈] Jupyter를 이용한 분석 환경 구축하기 - 허창현 클라우드 솔루션 아키텍트
[온라인교육시리즈] Jupyter를 이용한 분석 환경 구축하기 - 허창현 클라우드 솔루션 아키텍트[온라인교육시리즈] Jupyter를 이용한 분석 환경 구축하기 - 허창현 클라우드 솔루션 아키텍트
[온라인교육시리즈] Jupyter를 이용한 분석 환경 구축하기 - 허창현 클라우드 솔루션 아키텍트
 
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
 
Meteor IoT
Meteor IoTMeteor IoT
Meteor IoT
 
Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...
Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...
Auto Scalable 한 Deep Learning Production 을 위한 AI Serving Infra 구성 및 AI DevOps...
 
Boost 라이브리와 C++11
Boost 라이브리와 C++11Boost 라이브리와 C++11
Boost 라이브리와 C++11
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
 
eclipse에서 intelliJ IDEA로
eclipse에서 intelliJ IDEA로eclipse에서 intelliJ IDEA로
eclipse에서 intelliJ IDEA로
 
PyQGIS와 PyQt를 이용한 QGIS 기능 확장
PyQGIS와 PyQt를 이용한 QGIS 기능 확장PyQGIS와 PyQt를 이용한 QGIS 기능 확장
PyQGIS와 PyQt를 이용한 QGIS 기능 확장
 

파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)

  • 1. 파이썬 데이터과학 이태영 se2n@naver.com 파이썬을 이용한 데이터 분석, 그리고 머신러닝 실전 입문 1일차
  • 2. 이태영서울시립대 컴퓨터과학부 학사 고려대 전자컴퓨터공학과 석사 (경력) 2010 비씨카드 포인트 서비스 개발 업무 2012 FEP/대행승인/스피드비씨 펌뱅킹 개발 업무 2015 FEP 실시간 분석 모니터링 시스템 개발 구축 2015 BC 집현전 대상 ‘오픈소스를 활용한 빅데이터 플랫폼 구축’ 2018 BC R&D Cell 최우수상 ‘AI 기반 서비스 플랫폼 구축’ (특허/논문) 2012, 고객 단말기의 맥 어드레스 정보를 이용한 결제 방법 및 시스템 2013, 고객 단말기의 맥 어드레스 정보를 이용한 결제 방법 및 시스템 2014, 카드 상품 추천 방법 및 카드사 서버 2014, 사용 업종 예측을 위한 카드 사용 패턴 분석 방법 및 수행 서버 2015, 가맹점 개인화 추천 방법 및 가맹점 추천 서버 2017, Scalable 네트워크 아키텍처와 In-memory 컴퓨팅에 기반한 실시간 결제 분석 시스템, 고려대. 2018, Abnormal Payment Transaction Detection Scheme based on Scalable Architecture and Redis Cluster, IEEE. 무슨 경험으로 강의를 하나요? @관심사 : Scalable Architecture, Network Architecture, Machine Learning, Object Detection, Visualization, Pattern Recognition 비씨카드 (2010~) se2n@naver.com
  • 3. 독서백편의자현(讀書百遍義自見) 삽질할 용기 강의자료 100번도 말고 딱 3번만 복습 그리고 궁금하면 질문!
  • 4. 이번 과정을 통해 배울 지식 1. 파이썬 환경 • 개발환경 구축 • jupyter noteobok 2. 데이터 분석 • numpy • pandas • 시계열 거래 분석 • 거래 로그 분석 방법 • 선형/다항 회귀 분석 3. 데이터 분석과 시각화 • matplotlib • seaborn 4. 실전, 데이터분석 • 워드 클라우드 • 지도 시각화 • 19대 대선 결과 분석 • 서울시 부동산 예측 분석 • 자연어처리와 웹 크롤링 5. 머신러닝 • 머신러닝 기초 • 베이지안 네트워크 • 군집화 알고리즘 • 인공신경망 • 추천 시스템 • 마코프 모델과 챗봇
  • 6. 파이썬을 배우고 싶어요. 그런데 뭘로 코딩하지? Eclipse Jupyter 무겁지만 강력하다 빠르고 강력하다
  • 7. Jupyter Interactive computing python • Powerful interactive shells (terminal and Qt-based). • A browser-based notebook with support for code, text, mathematical expressions, inline plots and other rich media. • Support for interactive data visualization and use of GUI toolkits. • Flexible, embeddable interpreters to load into your own projects. • Easy to use, high performance tools for parallel computing.
  • 8. • 대화형 컴퓨팅으로 분석 프로그래밍 최적합 • 운영체제의 쉘 파일 시스템과 통합되어있음 • 웹기반의 대화형 노트북 지원으로 수식, 표, 그림 등을 표현 가능 • 가볍고 빠른 병렬컴퓨팅 엔진 이용 • 코딩과 문서화, 테스트까지 한 화면에 OK Jupyter Interactive computing python
  • 9. • python 3.6.6 설치 (윈도우는 MS Build Tools 2015 이상 함께 설치) • numpy 설치 • pandas 설치 • ipython 설치 • matplotlib 설치 • jupyter 설치 • notebook 설치 • 인터넷이 잘 된다면 pip install numpy pip install pandas pip install ipython pip install matplotlib pip install jupyter pip install notebook • 인터넷이 차단된 환경이라면 인터넷이 되는 환경에서 패키지들을 다운로드 pip download <패키지들> 다운로드 패키지들을 들여온 다음에 아래 명령어로 설치 pip install --no-index --find-links=. <패키지들> Jupyter Interactive computing python
  • 10. • 패키지 리스트 파일 이용한 설치 • numpy 설치 • pandas 설치 • ipython 설치 • matplotlib 설치 • jupyter 설치 • notebook 설치 • 패키지 리스트 작성 (예, req.txt) numpy pandas ipython matplotlib jupyter notebook 1. 인터넷 설치 pip install -r req.txt 2. 패키지 다운로드 설치 pip download -r req.txt pip install --no-index --find-links=. -r req.txt Jupyter Interactive computing python
  • 11. Jupyter Interactive computing python c = get_config() c.NotebookApp.ip = '*' c.NotebookApp.open_browser = False c.NotebookApp.port = 8888 c.NotebookApp.token = '' jupyter_notebook_config.py 설정 $ jupter notebook --generate-config 최초 Config 파일 생성 시 Jupyter 디렉토리 위치 Windows %USERNAME%.jupyter Linux ~/.jupyter ※비밀번호를 세팅하려면 c.NotebookApp.password 항목에 SHA 값을 설정
  • 12. Jupyter Interactive computing python • 만약 웹서버를 통해 IPytho notebook을 이용할 것이라면 비밀번호 설정 필요 c = get_config() c.NotebookApp.ip = '*' c.NotebookApp.open_browser = False c.NotebookApp.password = u‘sha1:3bf58406dd60:a965f3ac8e10a3637c011ba47dec1d081bbaf834' c.NotebookApp.port = 8888 In [1]: from notebook.auth import passwd In [2]: passwd() Enter password: Verify password: Out[2]: 'sha1:3bf58406dd60:a965f3ac8e10a3637c011ba47dec1d081bbaf834‘ • 콘솔창에서 ipython 으로 접속하여서 아래처럼 비밀번호 생성 후 복사 • jupyter_notebook_config.py 에서 password 영역에 붙여넣기 복사 & 붙여넣기 실행 명령어 jupyter notebook
  • 13. Jupyter Notebook Web browser based Python IDE 코드를 타이핑 치고 Ctrl+Enter 결과 표시
  • 14. Jupyter Notebook 파이썬 스크립트 생성 • Notebooks – Python 선택
  • 15. Jupyter Notebook 파이썬 스크립트 생성 • Notebooks – Python 선택 클릭해서 저장되는 노트북 파일명 변경 Cell은 4가지 형식 존재 Cell 종류 설명 • Code : 파이썬 코드 • MarkDown : 일종의 마크업 언어. 엔하위키나 텀블러에서 사용 중 • Raw NBCovert : IPython 노트북 날 코딩(?) • Heading : <html>의 <head> 태그와 유사한 기능
  • 16. Jupyter Notebook 단축키 (Shortcut) • Edit Mode : 셀 안에서 사용하는 단축키 • Command Mode : 셀 경계에서 사용하는 단축키 • h 를 누르면 기본 단축키에 대해 어느 정도 나온다. Edit mode 단축키Command mode 단축키 마우스 클릭하고
  • 17. Jupyter Notebook 단축키 (Shortcut) : Edit Mode 단축키 키보드 기능 키보드 기능 Tab 코드 자동완성, 들여쓰기(intent) Ctrl-Left 한 단어 좌측 이동 Shift-Tab 툴팁 Ctrl-Right 한 단어 우측 이동 Ctrl-] 들여쓰기(intent) Ctrl-Backspace 이전 단어 삭제 Ctrl-[ 내어쓰기(detent) Ctrl-Delete 이후 단어 삭제 Ctrl-a 전체 선택 Esc command mode Ctrl-z undo Ctrl-m command mode Ctrl-Shift-z redo Shift-Enter run cell, 다음 셀 선택 Ctrl-y redo Ctrl-Enter run cell Ctrl-Home 셀 처음으로 이동 Alt-Enter run cell, 다음 셀 삽입 Ctrl-End 셀 끝으로 이동 Ctrl-Shift-- 셀 분할 Ctrl-s 노트북 파일 저장
  • 18. Jupyter Notebook 단축키 (Shortcut) : Command Mode 단축키 키보드 기능 키보드 기능 Enter Edit mode 진입 c 셀 복사 Shift-Enter run cell, 다음 셀 선택 Shift-v 위에 붙여넣기 Ctrl-Enter run cell v 아래 붙여넣기 Alt-Enter run cell, 다음 셀 삽입 x 셀 잘라내기 y Code 셀로 변환 dd 셀 삭제 m Markdown 셀로 변환 z undo 이전 삭제 복구 r Raw NB 셀로 변환 Shift-m 아래 셀과 병합(merge) 1 Markdown : H1 s 노트북 저장 2 Markdown : H2 Ctrl-s 노트북 저장 3 Markdown : H3 l 해당 셀의 라인번호 토글 4 Markdown : H4 o 결과값 토글 5 Markdown : H5 Shift-o 결과값 토글(scrolling) 6 Markdown : H6 h keyboard shortcuts a 위에 셀 삽입 ii interrupt kernel b 아래 셀 삽입 00 restart kernel k / 방향키 위 이전 셀로 이동 j / 방향키 아래 다음 셀로 이동
  • 19. Jupyter Notebook Cell : Markdown • Markdown language 기반으로 Document 작성 (Wikipedia처럼 작성 방식) • 코드에 대한 설명이 가능하다. • 수학수식 표현도 가능 (Mathjax) 내용을 적고 Ctrl+Enter
  • 20. Jupyter Notebook Cell : Markdown • 제목(Head 태그) # 텍스트 # 하나를 쓰면 HTML의 <h1> 태그 # 두개를 쓰면 HTML의 <h2> 태그. 최대 6개까지 쓸 수 있다. • 리스트 (li 태그) • 번호 없는 리스트 : -텍스트 , +텍스트, *텍스트 • 번호 있는 리스트 : 숫자.텍스트 • 기울인 글씨(Italic 태그) : _텍스트_ , *텍스트* • 굵은 글씨(Strong 태그) : __텍스트__ , **텍스트** • 인용(cite) : >텍스트 • 인라인 링크 : [텍스트](링크) • 수평선(hr 태그) : --- , *** , ___
  • 21. Jupyter Notebook Cell : Code • 파이썬의 코드를 각 셀에 원하는 만큼을 작성하여 실행하면 메모리 상에 반영된다. • 위, 아래 위치가 달라도 실행한 스텝 번호(In [번호])가 높을 수록 최근에 수행된 영역이다. 방향 버튼을 이용하여 Cell의 위치를 변경 가능
  • 22. Jupyter Notebook Magic Keyword (매직 명령어) • 자주 사용하는 IPython 매직 명령어 • %(명령어) : 셀 내의 라인 독립 실행 • %%(명령어) : 셀 내의 전체 내용 관련 실행 매직 명령어 기능 %quickref IPython의 빠른 도움말 표시 %magic 모든 매직 함수에 대한 상세 도움말 출력 %debug 최근 예외 트레이스백의 하단에서 대화형 디버거로 진입 %hist 명령어 입력(그리고 선택적 출력) history 출력 %pdb 예외가 발생하면 자동으로 디버거로 진입 %run script.py IPython 내에서 파이썬 스크립트 실행 %timeit statement statement를 여러차례 실행한 후 평균 실행 시간을 출력. 매우 짧은 시간 안에 끝 나는 코드의 시간을 측정할 때 유용 %%writefile 파일명 filename인 파일을 생성 %save 파일명 from-to IPython의 이미 실행된 Step번호 구간대 명령어를 파일로 저장
  • 23. Jupyter Notebook Magic Keyword (매직 명령어) • 자주 사용하는 IPython 매직 명령어 • %(명령어) : 셀 내의 라인 독립 실행 • %%(명령어) : 셀 내의 전체 내용 관련 실행
  • 24. Jupyter Notebook Magic Keyword (매직 명령어) : TIP • (리눅스/유닉스만) %%writefile으로 스크립트 저장 후 %run으로 실행하려면 파이썬 스크립트에 한글이 포함될 때는 #!(샤방) 파이썬 패스, 언어 타입 정의 필요하다. #!/usr/bin/python #-*- coding: utf-8
  • 25. Jupyter Notebook 운영체제와 함께 사용하기 • IPython에서 운영체제의 자체 명령어를 실행하기 위해서는 !(명령어)로 수행
  • 26. Jupyter Notebook 운영체제와 함께 사용하기 • !(명령어)로 수행된 출력결과를 IPython의 데이터로 사용 가능
  • 27. Jupyter Notebook ipdb 디버깅을 이용한 코드 분석 • 매직 명령어 %debug 혹은 %%debug
  • 28. Jupyter Notebook ipdb 디버깅을 이용한 코드 분석 • ipdb 명령어 명령어 설명 h help 디버그 도움말. h만 입력하면 디버그 명령어 리스트 출력 h [명령어]를 입력하면 [명령어]에 대한 이용 도움말 w where 현재 위치의 Stack trace 출력 s step 현재 라인을 실행하고 다음 스텝으로 이동 n next 현재 라인을 실행하고 다음 라인으로 이동 r return 현재 함수가 끝날 때(return)까지 계속 실행 b break 특정 라인에 break point 설정 c continue break point가 있을 때까지 계속 실행 a args 현재 함수에 할당된 argument를 출력 p print value를 출력 cl clear [args] clear break point d down 현재 Stack에서 하위 Strack frame으로 이동 u up 현재 Stack에서 상위 Stack frame으로 이동 l list [from,to] 소스 출력 run run [args] Restart 디버거 프로그램. [args]을 입력하면 sys.argv에 할당됨 q quit 디버깅 종료
  • 29. Jupyter Notebook ipdb 디버깅을 이용한 코드 분석 • h (help) 명령어
  • 30. Jupyter Notebook ipdb 디버깅을 이용한 코드 분석 • step , up, down 명령어 In [8]: def A(): print 'world' def B(): print 'hello' A() ipdb> b 5 Breakpoint 1 at <ipython-input-8-c7a559c3b1ab>:5 ipdb> c hello > <ipython-input-8-c7a559c3b1ab>(5)B() 3 def B(): 4 print 'hello' 1---> 5 A() ipdb> s --Call-- > <ipython-input-8-c7a559c3b1ab>(1)A() ----> 1 def A(): 2 print 'world' 3 def B(): ipdb> s > <ipython-input-8-c7a559c3b1ab>(2)A() 1 def A(): ----> 2 print 'world' 3 def B(): ipdb> u > <ipython-input-8-c7a559c3b1ab>(5)B() 3 def B(): 4 print 'hello' 1---> 5 A() ipdb> d > <ipython-input-8-c7a559c3b1ab>(2)A() 1 def A(): ----> 2 print 'world' 3 def B(): A 함수로 진입 상위 Stack으로 이동 하위 Stack으로 이동 다음 스텝 %debug B()
  • 31. • ipdb 명령어 명령어 설명 h help 디버그 도움말. h만 입력하면 디버그 명령어 리스트 출력 h [명령어]를 입력하면 [명령어]에 대한 이용 도움말 w where 현재 위치의 Stack trace 출력 s step 현재 라인을 실행하고 다음 스텝으로 이동 n next 현재 라인을 실행하고 다음 라인으로 이동 r return 현재 함수가 끝날 때(return)까지 계속 실행 b break 특정 라인에 break point 설정 c continue break point가 있을 때까지 계속 실행 a args 현재 함수에 할당된 argument를 출력 p print value를 출력 cl clear [args] clear break point d down 현재 Stack에서 하위 Strack frame으로 이동 u up 현재 Stack에서 상위 Stack frame으로 이동 l list [from,to] 소스 출력 run run [args] Restart 디버거 프로그램. [args]을 입력하면 sys.argv에 할당됨 q quit 디버깅 종료 Jupyter Notebook ipdb 디버깅을 이용한 코드 분석
  • 33. Numpy 기초 사용법 • Numerical Python • C언어로 구현된 저수준 고성능 라이브러리 • 반복문을 작성할 필요 없이 전체 데이터 배열에 대한 빠른 연산 지원 • 배열 데이터를 디스크에 쓰거나 읽을 수 있는 도구와 메모리에 올려진 파일에 사용하는 도구 • 빠르고 메모리를 효율적으로 사용하여 다차원 배열 ndarray 지원 • 선형대수, 난수 발생기, 푸리에 변환 기능 import numpy as np ar_list = [i for i in range(20)] np_list = np.array(ar_list) %%timeit np_list * 100 661 ns ± 6.17 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) %%timeit ar_list * 100 4.04 µs ± 33.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  • 34. Numpy 기초 사용법 • 스칼라/벡터/행렬 • 스칼라는 number • 벡터(vector)는 숫자들의 list • 행렬(matrix)는 숫자들의 array(rows, columns)
  • 35. Numpy 기초 사용법 • numpy 배열 (1/2) • numpy 배열을 만들 때는 np.array() 메소드 이용 • np.array()는 파이썬의 리스트를 numpy,ndarray 형태로 변환 • numpy는 다차원 행렬로 표현하고, 계산하기 쉬움 arr = [[1,2,3,4], [5,6,7,8]] arr2= np.array(arr) arr2.ndim Out[]:2 arr2.shape Out[]:(2, 4) arr2 * 10 Out[]: array([[10, 20, 30, 40], [50, 60, 70, 80]]) arr2 + 10 Out[]: array([[11, 12, 13, 14], [15, 16, 17, 18]])
  • 36. Numpy 기초 사용법 • numpy 배열 (2/2) • zeros : 0으로 초기화된 배열, ones : 1로 초기화된 배열 • linespace : 선형 구간에서 지정 구간의 수만큼 분할 • logspace : 로그 구간에서 지정 구간의 수만큼 분할 • empty : 배열을 메모리에 생성만하고 특정한 값을 초기화하지 않는 배열 (초기화 시간 단축) np.zeros(5) Out[]: array([0., 0., 0., 0., 0.]) np.ones(5) Out[]: array([1., 1., 1., 1., 1.]) np.linspace(0, 10, 5) # (시작, 끝, 개수) Out[]: array([ 0. , 2.5, 5. , 7.5, 10. ]) np.logspace(0, 100, 5) Out[]: array([1.e+000, 1.e+025, 1.e+050, 1.e+075, 1.e+100]) np.empty(5) Out[]: array([0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 0.00000000e+000, 1.70704615e-312])
  • 37. Numpy 기초 사용법 • numpy 산술 연산 • numpy는 배열과 스칼라 값을 조합으로 산술 연산이 가능 • numpy 배열은 스칼라 값에 의해 원소별(element-wise)로 한 번씩 수행 (브로드캐스트) arr = np.array([[1,2,3,4], [5,6,7,8]] ) arr * 10 Out[]: array([[10, 20, 30, 40], [50, 60, 70, 80]]) arr + 10 Out[]: array([[11, 12, 13, 14], [15, 16, 17, 18]]) arr / 2 Out[]: array([[0.5, 1. , 1.5, 2. ], [2.5, 3. , 3.5, 4. ]]) arr % 2 Out[]: array([[1, 0, 1, 0], [1, 0, 1, 0]], dtype=int32)
  • 38. Numpy 기초 사용법 • 다차원으로 변환 • numpy는 배열은 reshape로 N차원 매트릭스로 변환 가능 • reshape 명령어 중 원소는 -1로 대체할 수 있다. • arr.reshape(4,-1) : 4개 ROW를 가지는 행렬 • arr.reshape(-1,5) : 5개 COLUMN을 가지는 행렬 arr = np.array(range(0,20)) # 0~19까지 생성 arr_2d = arr.reshape(4,5) arr_2d Out[]: array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19]]) arr.reshape(4,-1) arr.reshape(-1, 5) Out[]: array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19]])
  • 39. Numpy 기초 사용법 • 다차원으로 변환 • flatten 메소드 : numpy 다차원 배열을 1차원 리스트로 변환 • np.newaxis :차원을 증가시킬 때 사용 arr_3d = arr.reshape(5, 2, 2) arr_2d.reshape(1,20) Out[]: array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]) arr_1d = arr_3d.flatten() arr_1d Out[]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,17, 18, 19]) arr_1d[np.newaxis] Out[]: array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]) arr_1d[np.newaxis, np.newaxis] Out[]: array([[[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]])
  • 40. Numpy 배열 붙이기 • 행(COLUMN)의 수나 열(ROW)의 수가 같은 두 개 이상의 배열을 잇는(concatenate) 방법 • hstack : ROW의 수가 같은 경우, COLUMN으로 붙임 (좌측에서 옆으로 붙임) • vstack : COLUMN의 수가 같은 경우, ROW으로 붙임 (위에세서 아래로 붙임) • stack : 배열을 별개 차원으로 구성한다. (2차원 배열 두 개를 합치면 3차원 배열로.) a1 = np.ones((3,4)) #1로 채워진 배열 생성 a2 = np.zeros((3,4)) #0으로 채워진 배열 생성 np.hstack([a1, a2]) Out[]: array([[1., 1., 1., 1., 0., 0., 0., 0.], [1., 1., 1., 1., 0., 0., 0., 0.], [1., 1., 1., 1., 0., 0., 0., 0.]]) np.vstack([a1,a2]) Out[]: array([[1., 1., 1., 1.], [1., 1., 1., 1.], [1., 1., 1., 1.], [0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]) np.stack([a1,a2]) Out[]: array([[[1., 1., 1., 1.], [1., 1., 1., 1.], [1., 1., 1., 1.]], [[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]]]) #axis=1 지정 시각 배열의 row별 묶음 np.stack([a1,a2], axis=1) array([[[1., 1., 1., 1.], [0., 0., 0., 0.]], [[1., 1., 1., 1.], [0., 0., 0., 0.]], [[1., 1., 1., 1.], [0., 0., 0., 0.]]])
  • 41. Numpy 기술통계 • 집계 합수(aggregate function) • max (배열의 최대값) min (배열의 최소값) mean (배열의 평균 값) • numpy의 모든 집계 함수는 AXIS 기준으로 계산이 이루어짐 arr = np.array([[5,6,7,8,9], [0,1,2,3,4]]) arr.max() Out[]: 9 arr.min() Out[]: 0 arr.mean() Out[]: 4.5 arr.max(axis=1) Out[]: array([9, 4]) arr.min(axis=1) Out[]: array([5, 0]) arr.mean(axis=1) Out[]: array([7., 2.]) arr.max(axis=0) Out[]: array([5, 6, 7, 8, 9]) arr.min(axis=0) Out[]: array([0, 1, 2, 3, 4]) arr.mean(axis=0) Out[]: array([2.5, 3.5, 4.5, 5.5, 6.5])
  • 42. Numpy 랜덤 함수 • 난수(random number) np.random.seed(0) # 랜덤 seed 지정 np.random.randint(0, 1000) # 0~1000사이 난수 생성 Out[]: 629 np.random.rand(5) #5개의 난수 생성 Out[]: array([0.22232139, 0.38648898, 0.90259848, 0.44994999, 0.61306346]) np.random.rand(3,5) #3x5 행렬 형태의 난수 생성 Out[]: array([[0.888609 , 0.90658127, 0.55368029, 0.83453863], [0.29628516, 0.2548365 , 0.59444402, 0.14268807], [0.13459794, 0.81022365, 0.69110336, 0.37632546]]) x = np.arange(10) # 0~9까지 배열 생성 Out[]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) np.random.shuffle(x) # 배열 x의 순서를 무작위로 변경 () Out[]: array([5, 0, 4, 2, 3, 6, 8, 7, 9, 1])
  • 43. Numpy 데이터 샘플링 • 데이터 샘플링 • 샘플링(sampling) : 존재하는 데이터 집합에서 일부를 무작위로 선택 • np.random.choice( a, size=None, replace=True, p=None) x = np.random.choice(10, 10, replace=False) # shuffle 기능과 동일 Out[]: array([0, 7, 1, 5, 2, 3, 9, 6, 8, 4]) np.random.choice(x, 5, replace=True) # 5개 샘플링, 중복 허용 Out[]: array([2, 4, 6, 3, 6]) np.random.choice(4, 3, replace=False, p=[0.4, 0.2, 0, 0.4]) # 선택 확률 별도 지정 Out[]: array([0, 3, 1]) a 배열, 혹은 정수. 정수를 입력할 경우 range(a) 명령으로 데이터 생성 size 샘플할 개수 지정 replace True이면 한 번 선택한 데이터를 다시 추출 가능 (중복 추출) p a 배열의 데이터들에 대해 선택될 수 있는 확률 지정
  • 44. Numpy 비교 연산 • 비교 연산 처리 • 인덱싱 영역에 조건 값을 입력하면 해당 조건에 맞는 데이터 추출 가능 • 인덱싱 영역에 조건 값을 입력하고 해당 조건에 맞는 영역에 새로운 값을 대입 가능 f = np.random.rand(3,4) Out[]: array([[0.888609 , 0.90658127, 0.55368029, 0.83453863], [0.29628516, 0.2548365 , 0.59444402, 0.14268807], [0.13459794, 0.81022365, 0.69110336, 0.37632546]]) tf = f > 0.3 Out[]: array([[ True, True, True, True], [False, False, True, False], [False, True, True, True]]) f[ f > 0.3 ] = 1 Out[]: array([[1. , 1. , 1. , 1. ], [0.29628516, 0.2548365 , 1. , 0.14268807], [0.13459794, 1. , 1. , 1. ]])
  • 45. Numpy 유니버설 함수 • ufunc라고 불리는 유니버설 함수. • ndarray 안에 있는 데이터 원소별로 연산을 수행 • 고속으로 수행할 수 있는 벡터화된 Wrapper 함수 x = np. linspace(-5, 5, 20) # 선형공간 0~10에서 20개 데이터 고르게 추출 np.sqrt(x) # 제곱근 연산 √x np.exp(x) # 지수함수 연산 ex (e=2.718281…) np.abs(x) # 절대값 연산 np.ceil(x) # 소수점 올림 연산 np.floor(x) # 소수점 내림 연산 np.round(x) # 소수점 반올림 연산 np.cos(x), np.sin(x) # sin함수, cos함수 처리 (그 외 다양한 삼각함수들 존재) np.power(x, n) # n 제곱 처리 np.log(x) # 자연로그 연산 (logex) np.log10(x) # 로그10 연산 (log10x) np.log2(x) # 로그2 연산 (log2x) np.mod(x, n) # 각 요소별로 n으로 나눈 뒤의 나머지 추출
  • 46. Numpy 유니버설 함수 import matplotlib.pyplot as plt import numpy as np x = np.linspace(-5, 5, 100) y = x y_sin = np.sin(x) y_cos = np.cos(x) y_sqrt = np.sqrt(x) y_log = np.log(x) y_log10 = np.log10(x) fig= plt.figure() ax = fig.add_subplot(111) ax.plot(x, y, label='y=x') ax.plot(x, y_sin, label='sin') ax.plot(x, y_cos, label='cos') ax.plot(x, y_sqrt, label='sqrt') ax.plot(x, y_log, label='log') ax.plot(x, y_log10, label='log10') ax.legend() plt.show() • matplotlib는 이후 데이터시각화에서 다룰 예정 • plot 그래프에 x 좌표, y 좌표에 어떤 데이터가 입력되는지 확인하고 눈으로 보는 데 의의두자!
  • 47. Numpy 최소제곱법 : 선형회귀 • 최소제곱법 (Method of Least Squares) • 함수 값과 측정 값의 차이인 오차를 제곱한 것의 합이 최소가 되는 함수 Y = F(X)를 구하는 방법 • f(x) = ax + b의 경우 f(x)를 최소화 하도록 a, b를 결정 짓는 방법 • σ𝑖=1(𝑦𝑖 − 𝑎𝑥𝑖 − 𝑏)2 • 각 데이터 좌표에서 최적함수까지의 거리 구함 • 최적의 함수라면, 이 차이가 가능한 한 최소화 • 최소제곱법은 이 편차를 최소화하기 위한 방법 • 이렇게 나온 선을 최소제곱선 혹은 선형회귀선 측정값 𝑦𝑖 𝑦𝑡𝑟𝑢𝑒 상수항 α 종속변수 𝑦 독립변수 𝑥 오차𝑒𝑖
  • 48. Numpy 선형회귀(Linear Regression) • polyfit과 poly1d를 이용한 선형회귀 • np.polyfit(x, y, degree) : 주어진 측정 값들로 다항식의 계수를 구함 • x array, y array값을 입력, degree는 다항식의 차수 • (degree = 1) 1항식 경우 y = ax + b → 리턴 값 array([a, b]) • (degree = 2) 2항식 경우 y = ax2 + bx + c → 리턴 값 array([a, b, c]) • (degree = 3) 3항식 경우 y = ax3 + bx2 + cx + d → 리턴 값 array([a, b, c, d]) • np.poly1d(coefficients) : 다항식 계수로 1차원 다항식 함수 생성 • fx = np.poly1d([1,2,3]) : 1x2 + 2x + 3 식을 갖는 다항식 함수 생성 • fx([1,2,3,4,5]) → x 값으로 1,2,3,4,5를 받아 다항식 fx 함수로 연산 x = np.arange(0, 10, 0.01) # 0~10까지 0.01 단위로 배열 생성 y = 3*x + 5 # 3*x + 5 연산한 배열 생성 y_noise = y + np.random.randn(len(y)) # 랜덤으로 노이즈 생성 fp1 = np.polyfit(t, y_noise, 1) # polyfit 다항식 계수 생성 Out[]: array([3.0042063 , 4.94969849]) fx = np.poly1d(fp1) # poly1d 다항식 1차원 함수 생성 fx([0,1,2,3]) # 함수를 이용한 계산 Out[]: array([ 4.94969849, 7.95390479, 10.95811109, 13.96231739])
  • 49. Numpy 선형회귀(Linear Regression) • https://github.com/sh2orc/datascience에서 trns_1day_series 다운로드 import pandas as pd #pandas library import numpy as np #numpy library df = pd.read_csv('trns_1day_series') x = df['APPROVAL'] #승인건수 Series 추출 fp1 = np.polyfit(x.index, x, 1) #1차 다항식 계수 fp2 = np.polyfit(x.index, x, 2) #2차 다항식 계수 fp3 = np.polyfit(x.index, x, 3) #3차 다항식 계수 fx1 = np.poly1d(fp1) #1차 다항식 함수 생성 fx2 = np.poly1d(fp2) #2차 다항식 함수 생성 fx3 = np.poly1d(fp3) #3차 다항식 함수 생성 df['REG_1'] = fx1(x.index) #1차 다항식 연산 df['REG_2'] = fx2(x.index) #2차 다항식 연산 df['REG_3'] = fx3(x.index) #3차 다항식 연산 df[['APPROVAL','REG_1','REG_2','REG_3']].plot()
  • 51. Pandas 기초 개념 • Pandas • Numpy 기반으로 개발되어 고성능 데이터 분석 가능 • R언어에서 제공하는 DataFrame 자료형 제공 • 명시적으로 축의 이름에 따라 데이터 정렬 가능한 자료구조 • 통합된 Time Series 분석 기능 • 누락된 데이터를 유연하게 처리할 수 있는 기능 import numpy as np import pandas as pd # Pandas 라이브러리 선언 logx = np.logspace(0, 1, 100) linx = np.linspace(0, 10, 100) df = pd.DataFrame() #Pandas의 DataFrame 생성 df['logspace'] = logx #컬럼명 logspace의 Series 데이터 df['linspace'] = linx #컬럼명 linespace의 Series 데이터 df.head() # DataFrame 상위 5개 보기 df.plot() # 그래프로 출력
  • 52. Pandas 기초 개념 • DataFrame • 레이블(Labeled)된 행(Column)과 열(Row)을 가진 2차원 데이터구조 • 칼럼 마다 데이터 형식이 다를 수 있음 • 각 행(Column)과 열(Row)들을 산술연산이 가능한 구조 • DataFrame 크기는 유동적으로 변경 가능 • DataFrame끼리 여러 가지 조건을 사용한 결합처리 가능 가 나 다 라 A 3 1 7 0 B 8 2 8 0 C 0 3 9 0 D 2 4 0 1 E 1 5 1 0 row column
  • 53. Pandas 기초 개념 • Series와 DataFrame • Series : 인덱스 라벨이 붙은 1차원 리스트 데이터 구조 • DataFrame : Series가 모인 2차원 테이블 데이터 구조 (인덱스와 컬럼 라벨이 붙음) • DataFrame이 핵심이고, Series는 개념으로 알아두자! A 3 B 8 C 0 D 2 E 1 가 나 다 라 A 3 1 7 0 B 8 2 8 0 C 0 3 9 0 D 2 4 0 1 E 1 5 1 0 index column Series DataFrame index
  • 54. Pandas 기초 개념 • Series와 DataFrame • Series 생성 : pd.Series(values, index=index, names=names) • DataFrame 생성 : pd.DataFrame(values, index=index, columns=cols) pd.Series([1,2,3,4], index=['one','two','three','four']) Out[]: one 1 two 2 three 3 four 4 dtype: int64 pd.DataFrame([1,2,3,4], index=['one','two','three','four'], columns=['number']) Out[]: number one 1 two 2 three 3 four 4
  • 55. DataFrame 생성 고객 금액 가맹점 카드 0 A 1000 0001 944020 1 B 2000 0002 480520 2 C 5000 0003 460220 ds = [ {'고객':'A', '금액':1000, '가맹점':'0001', '카드':'9440'}, {'고객':'B', '금액':2000, '가맹점':'0002', '카드':'4805'}, {'고객':'C', '금액':5000, '가맹점':'0003', '카드':'4602'} ] df = pd.DataFrame(ds) default List RoworientedColumnoriented ds = { '고객' :['A','B','C'], '금액' :[1000, 2000, 5000], '가맹점' :['0001', '0002', '0003'], '카드' :['9440', '4805', '4602'] } df = pd.DataFrame.from_dict(ds) #df = pd.DataFrame(ds) 가능 from_dict from_items ds = [['고객' ,['A', 'B', 'C']], ['금액' ,[1000, 2000, 5000]], ['가맹점' ,['0001', '0002', '0003' ]], [ '카드' ,['9440', '4805', '4602' ]] ] df = pd.DataFrame.from_items(ds) from_records Dictionary ds = [['A', 1000, '0001', '9440'], ['B', 2000, '0002', '4805'], ['C', 5000, '0003', '4602']] lb = ['고객', '금액', '가맹점', '카드'] df = pd.DataFrame.from_records(ds, columns=lb) #df = pd.DataFrame(ds, columns=lb) 가능
  • 56. Pandas DataFrame 생성 • CSV 형식 파일을 읽어 들여 DataFrame 생성 • pd.read_csv(path, sep='구분자', names=['컬럼명',..]) : 파일로부터 DataFrame 생성 • github.com/sh2orc/datascience에서 데이터셋 다운로드 df = pd.read_csv('titanic.csv', sep='t') #데이터가 TAB으로 구분되어 있는 경우 df.head() #컬럼 헤더가 없는 파일의 경우는 name= 옵션을 통해 지정해줄 수 있다. df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str) PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked 0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 NaN S 1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38 1 0 PC 17599 71.2833 C85 C 2 3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 NaN S 3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S MSG_CODE MSG_NAME 0 0100 MS승인요청 1 0110 MS승인응답 2 0300 IC승인 요청 3 0310 IC승인 응답 4 0420 MS승인취소 요청
  • 57. Pandas DataFrame 생성 • dictionary 객체로 DataFrame 생성 • dictionary 객체가 단순 {key:value}로 구성되어있을 경우 • pd.from_dict(ds, oriented='index', columns=['value에 대한 칼럼명']) firm_name={"03":"IBK기업은행", "11":"NH농협은행", "20":"우리카드", "23":"SC제일은행", "48":"새마을금고", "72":"우체국" } df = pd.DataFrame.from_dict(firm_name, orient='index', columns=['FIRM_NAME’]) df FIRM_NAME 03 IBK기업은행 11 NH농협은행 20 우리카드 23 SC제일은행 48 새마을금고 72 우체국
  • 58. Pandas Column명 변경 • DataFrame의 rename • pd.DataFrame.columns = [ '칼럼1', '칼럼2', … , ] 이용 • pd.DataFrame.rename( { 'OLD칼럼명' : 'NEW칼럼명', …, }, axis=1) 이용 • pd.DataFrame.rename(columns={ 'OLD칼럼명' : 'NEW칼럼명', …, }) 이용 df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str) df.head() df.rename({'MSG_CODE' : 'CODE'}, axis=1) #둘 다 같은 역할 df.rename(columns={'MSG_CODE' : 'CODE'}) MSG_CODE MSG_NAME 0 0100 MS승인요청 1 0110 MS승인응답 2 0300 IC승인 요청 3 0310 IC승인 응답 4 0420 MS승인취소 요청 CODE MSG_NAME 0 0100 MS승인요청 1 0110 MS승인응답 2 0300 IC승인 요청 3 0310 IC승인 응답 4 0420 MS승인취소 요청
  • 59. df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str) df = df.set_index('MSG_CODE') df['COUNT'] = [ np.random.randint(5,10) for i in range(len(df.index)) ] df.plot(kind='bar') MSG_NAME MSG_CODE 0100 MS승인요청 0110 MS승인응답 0300 IC승인 요청 0310 IC승인 응답 0420 MS승인취소 요청 Pandas DataFrame Index • index 지정 방법 • 생성 시점 : pd.read_csv(path, names=[], index_col=칼럼인덱스번호) • 생성 이후 : pd.DataFrame.set_index('칼럼명') Index로 지정 시 해당 데이터 컬럼이 데이터의 축이 된다.
  • 60. Pandas DataFrame Index • index 초기화 • reset_index() : 기존 index를 컬럼으로 위치시키고, 새로운 index를 생성한다. df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str) df = df.set_index('MSG_CODE') df['COUNT'] = [ np.random.randint(5,10) for i in range(len(df.index)) ] df = df.reset_index() set_index() reset_index() MSG_CODE MSG_NAME COUNT 0 0100 MS승인요청 9 1 0110 MS승인응답 7 2 0300 IC승인 요청 5 3 0310 IC승인 응답 7 4 0420 MS승인취소 요청 6 MSG_NAME MSG_CODE 0100 MS승인요청 0110 MS승인응답 0300 IC승인 요청 0310 IC승인 응답 0420 MS승인취소 요청
  • 61. Pandas 행(Column)과 열(Row) 삭제 • pd.DataFrame.drop([label, …, ], axis=0 또는 1) • 열(Row) 삭제 - label에 삭제할 row의 index들을 입력 • 행(Colum) 삭제 - label에 삭제할 column들을 입력. 이 때 axis=1로 지정 df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str) df['COUNT'] = [ np.random.randint(5,10) for i in range(len(df.index)) ] df.drop([0,1,3]) df.drop('COUNT', axis=1) MSG_CODE MSG_NAME COUNT 0 0100 MS승인요청 5 1 0110 MS승인응답 7 2 0300 IC승인 요청 7 3 0310 IC승인 응답 8 4 0420 MS승인취소 요청 7 MSG_CODE MSG_NAME COUNT 2 0300 IC승인 요청 7 4 0420 MS승인취소 요청 7 5 0430 MS승인취소 응답 8 6 9300 기타승인 요청 8 7 9310 기타승인 응답 5 MSG_CODE MSG_NAME 0 0100 MS승인요청 1 0110 MS승인응답 2 0300 IC승인 요청 3 0310 IC승인 응답 4 0420 MS승인취소 요청
  • 62. Pandas 행(Column)과 열(Row) 삭제 • 특정 컬럼 기준으로 삭제 방법 • 칼럼을 index로 지정하고, 삭제할 대상을 각각 하드코딩 • 칼럼을 index를 리스트로 추출하여, 삭제할 대상에 입력 df = pd.read_csv('msg_code', names=['MSG_CODE', 'MSG_NAME'], dtype=str) tf = df.set_index('MSG_CODE') tf.drop(['0100','0110']) #index 0100, 0110 기준 ROW 삭제 tf.index.str[:2] == '01' Out[]: array([ True, True, False, False, False, False, False, False, False, False, False, False]) tf.index[tf.index.str[:2] == '01'] Out[]: Index(['0100', '0110'], dtype='object', name='MSG_CODE') tf.drop(tf.index[tf.index.str[:2]=='01']) # 01로 시작하는 index 추출 후 ROW 삭제
  • 63. Pandas 선택과 변경 • DataFrame의 배열[ ] 내 값을 지정한 선택 • 숫자 인덱스 선택 : 열(ROW) • KEY값으로 선택 : 행(COLUMN) df = pd.DataFrame( np.arange(9).reshape(3,3), index=['r1','r2','r3'], columns=['c1','c2','c3']) df[:2] #슬라이싱 인덱스 기준은 ROW df[['c1','c2']] # [ ] 내에는 KEY 조회는 칼럼만 가능 df['r1'] # KEY 값을 인덱스 KEY로 지정 불가 KeyError: 'r1' c1 c2 c3 r1 0 1 2 r2 3 4 5 r3 6 7 8 c1 c2 c3 r1 0 1 2 r2 3 4 5 c1 c2 r1 0 1 r2 3 4 r3 6 7
  • 64. Pandas 선택과 변경 • DataFrame의 배열[ ] 내 (칼럼) 조건 지정 • 해당 지정된 칼럼의 조건에 의한 Boolean 선택 • 2개 이상의 조건은 각 조건별로 ( ) 묶음을 통해 AND/OR 조건 지정 df = pd.DataFrame( np.arange(9).reshape(3,3), index=['r1','r2','r3'], columns=['c1','c2','c3']) df[df.c1 > 4] #DataFrame 객체의 멤버 변수로 칼럼명 지정 접근 df[df['c1'] > 4] #DataFrame의 배열 Key로 칼럼명 지정 접근 df[(df.c1 > 1) & (df.c2 < 5)] #2개 이상의 조건 지정 때는 각 조건별로 ( )로 묶어줘야 함 c1 c2 c3 r1 0 1 2 r2 3 4 5 r3 6 7 8 c1 c2 c3 r3 6 7 8 c1 c2 c3 r3 6 7 8 c1 c2 c3 r2 3 4 5
  • 65. Pandas 선택과 변경 • DataFrame의 배열[ ] 내 (칼럼) 조건 지정 • df[ [칼럼명1, 칼럼명2, …, ] ] 형식으로 정의시 DataFrame 재정의 가능 • 재정의된 DataFrame은 마치 가상 뷰(View) 테이블처럼 구성 df = pd.DataFrame( np.arange(9).reshape(3,3), index=['r1','r2','r3'], columns=['c1','c2','c3']) df[ [‘c1’, ‘c2’] ] #c1, c2 칼럼으로만 DataFrame 재구성 df[ [‘c1’] ] #c1 칼럼으로만 DataFrame 재구성 c1 c2 c3 r1 0 1 2 r2 3 4 5 r3 6 7 8 c1 c2 r1 0 1 r2 3 4 r3 6 7 c1 r1 0 r2 3 r3 6
  • 66. Pandas 선택과 변경 • loc 인덱스 : 레이블 선택을 기반으로 한 인덱서 • df.loc[ <열 선택 조건> , <행 선택 조건> ] • 정수형(integer) 위치 지정으로는 선택 불가. df = pd.DataFrame(np.array([100,20000, 50,50000, 90, 50000]).reshape(3,2), columns=['성능','가격'], index=['BC1','BC2','BC3']) df.loc['BC1'] # loc[ ]에 단독 KEY로 입력할 경우 ROW 기준으로 조회 성능 100 가격 20000 Name: BC1, dtype: int32 df.loc['BC1', '가격'] # BC1 열의 '가격' 행의 값을 조회 20000 df.loc[(df.성능 % 50 == 0), "성능"] # 전체 열에서 성능%50 == 0 조건으로 필터링 중 "성능" 칼럼 조회 BC1 100 BC2 50 Name: 성능, dtype: int32 성능 가격 BC1 100 20000 BC2 50 50000 BC3 90 50000
  • 67. Pandas 선택과 변경 • loc 인덱스 데이터 변경 • df.loc[ <열 선택 조건> , <행 선택 조건> ] = '변경할 값' • loc를 이용하여 조건에 해당하는 전체 데이터를 변경 가능 df = pd.DataFrame(np.array([100,20000, 50,50000, 90, 50000]).reshape(3,2), columns=['성능','가격'], index=['BC1','BC2','BC3']) df.loc[(df.성능 % 50 == 0), "성능"] # 전체 열에서 성능%50 == 0 조건으로 필터링 중 "성능" 칼럼 조회 BC1 100 BC2 50 Name: 성능, dtype: int32 df.loc[(df.성능 % 50 == 0), "성능"] = 70 # 선택된 "성능" 칼럼의 데이터들을 70으로 전체 변경 df 성능 가격 BC1 100 20000 BC2 50 50000 BC3 90 50000 성능 가격 BC1 70 20000 BC2 70 50000 BC3 90 50000
  • 68. Pandas 정렬 (Sorting) • df.sort_values(by = [기준 칼럼명,…], ascending=True ) • 기준 컬럼명을 여러 개 지정하면 각 순서별로 정렬 기준 • ascending을 입력하지 않으면 True(오름차순)로 판단 df df.sort_values('성능', ascending=False) # '성능' 기준으로 내림차순 정렬 df.sort_values(['가격','성능'], ascending=False) # ['가격', '성능'] 순서대로 내림차순 정렬 성능 가격 BC1 70 20000 BC2 70 50000 BC3 90 50000 성능 가격 BC3 90 50000 BC1 70 20000 BC2 70 50000 성능 가격 BC3 90 50000 BC2 70 50000 BC1 70 10000
  • 69. Pandas 행/열 합계 • df.sum( axis=? ) • axis는 1과 0 값 이며 입력하지 않으면 0로 자동 처리 (칼럼 기준 합) • axis = 1로 입력시 각 열 기준으로 합산 df df.sum() # 각 칼럼별 합계 성능 230 가격 120000 dtype: int64 df.sum(axis=1) # 각 로우별 합계 BC1 20070 BC2 50070 BC3 50090 dtype: int64 df['ROW_SUM'] = df.sum(axis=1) # 신규 칼럼 추가 df.loc['COL_SUM', :] = df.sum() # 신규 로우 추가 df 성능 가격 ROW_SUM BC1 70 20000 20070 BC2 70 50000 50070 BC3 90 50000 50090 COL_SUM 230 120000 120230 성능 가격 BC1 70 20000 BC2 70 50000 BC3 90 50000
  • 70. Pandas 시계열 시간 관리 • pd.to_datetime('문자열', format='입력된 문자열의 시간포멧') • 문자열을 입력받아 Timestamp 객체로 변환. 파이썬 datetime 객체 변환 용이 • 시간포멧 기호 의미 자리수 출력 %Y 년 4 2018 %y 년 2 18 %m 월 2 09 %d 일 2 07 %H 시 (24시간) 2 17 %M 분 2 32 %S 초 2 58 %f 마이크로초 (1/10-6초) 6 004321 #문자열 입력을 받아서 Timestamp 객체로 변환 beg_time = pd.to_datetime('20180907 12:30:05', format='%Y%m%d %H:%M:%S') end_time = pd.to_datetime('20180907 12:31:05', format='%Y%m%d %H:%M:%S') Out[]: Timestamp('2018-09-07 12:30:05') end_time - beg_time Out[]: Timedelta('0 days 00:01:00')
  • 71. Pandas 시계열 시간 관리 • pd.date_range('시작 일시 ', '종료 일시' , freq='빈도 포멧') • 시작 일시와 종료 일시 사이에 빈도별 datetime 객체를 갖는 리스트 생성 • 빈도포멧 : {숫자}{기호}로 사용되며 숫자는 기호에 의미하는 기준 단위 #일자를 받아 월별 빈도 리스트 pd.date_range('20180101', '20180901', freq='M') #월말 Out[]: DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31', '2018-04-30'], dtype='datetime64[ns]', freq='M') pd.date_range('20180101', '20180901', freq='MS') #월초 Out[]: DatetimeIndex(['2018-01-01', '2018-02-01', '2018-03-01', '2018-04-01', '2018-05-01'], dtype='datetime64[ns]', freq='MS') 기호 의미 s 초 T 분 H 시간 D 일(day) W 주(일요일) W-MON 주(월요일) M 각 달의 마지막 날 MS 각 달의 첫날
  • 72. Pandas 시계열 시간 관리 • pd.date_range('시작 일시 ', '종료 일시' , freq='빈도 포멧') • 시작 일시, 종료 일시 변수는 문자열, datetime 객체 • datetime 객체의 차를 구하려면 datetime.timedelta 함수를 사용 #현재 시점의 시간으로 부터 앞으로 5분 사이의 10초당 간격 리스트 추출 import datetime import pandas as pd beg_time = datetime.datetime.now() #현재시간 datetime 객체 end_time = datetime.datetime.now() + datetime.timedelta(minutes=5) #5분 이후 datetime 객체 pd.date_range(beg_time, end_time, freq='10s') #10초 간격으로 시간 리스트 구함 Out[]: DatetimeIndex(['2018-09-07 09:38:19.593836', '2018-09-07 09:38:29.593836', '2018-09-07 09:38:39.593836', '2018-09-07 09:38:49.593836', '2018-09-07 09:38:59.593836', '2018-09-07 09:39:09.593836', ......... '2018-09-07 09:42:59.593836', '2018-09-07 09:43:09.593836', '2018-09-07 09:43:19.593836'], dtype='datetime64[ns]', freq='10S')
  • 73. Pandas DataFrame Merge • 2개 DataFrame을 Join 하는 방법 : merge • pd.merge( df1, df2, on=['KEY',…], how='inner') • on = [ ]에 들어갈 값들은 병합 기준이 되는 칼럼명 (입력하지 않으면 동일 칼럼명들 지정) • how = 'inner', 'left', 'right', 'outer' 중 선택 1개 (입력하지 않으면 inner로 지정 처리) code = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']} code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']} tf = pd.DataFrame.from_dict(code) vf = pd.DataFrame.from_dict(code2) tf vf pd.merge(tf, vf) # 동일 칼럼명인 CODE 기준으로 INNER JOIN 처리 CODE NAME 0 A 아 1 B 비 2 C 씨 3 D 디 4 E 이 CODE VALUE 0 A 1 1 B 2 2 C 3 3 X 4 4 Y 5 CODE NAME VALUE 0 A 아 1 1 B 비 2 2 C 씨 3
  • 74. code1 = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']} code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']} df1 = pd.DataFrame.from_dict(code1) df2 = pd.DataFrame.from_dict(code2) rf = pd.merge(df1, df2, on=['CODE'], how='inner') # how를 지정하지 않아도 기본 inner로 동작 Pandas Merge - Inner Join • pd.merge( df1, df2, on=['CODE'], how='inner') • 기준 칼럼에서 같은 값을 가진 열들의 요소들을 합친다. • 기준 칼럼에서 같은 값이 아닌 대상들은 모두 제외된다. CODE NAME 0 A 아 1 B 비 2 C 씨 3 D 디 4 E 이 CODE VALUE 0 A 1 1 B 2 2 C 3 3 X 4 4 Y 5 CODE NAME VALUE 0 A 아 1 1 B 비 2 2 C 씨 3 df1 df2 + = rf
  • 75. code1 = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']} code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']} df1 = pd.DataFrame.from_dict(code1) df2 = pd.DataFrame.from_dict(code2) rf = pd.merge(df1, df2, on=['CODE'], how='left') Pandas Merge - Left Join • pd.merge( df1, df2, on=['CODE'], how='left') • 왼쪽 DataFrame의 다른 열 값들을 보존하며 오른쪽 DataFrame을 끼워 맞춘다. • df1.CODE의 전체를 보존하며 병합, df2.CODE에서 없는 것들은 NaN으로 채움 CODE NAME 0 A 아 1 B 비 2 C 씨 3 D 디 4 E 이 CODE VALUE 0 A 1 1 B 2 2 C 3 3 X 4 4 Y 5 CODE NAME VALUE 0 A 아 1 1 B 비 2 2 C 씨 3 3 D 디 NaN 4 E 이 NaN df1 df2 + = rf
  • 76. code1 = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']} code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']} df1 = pd.DataFrame.from_dict(code1) df2 = pd.DataFrame.from_dict(code2) rf = pd.merge(df1, df2, on=['CODE'], how='right') Pandas Merge - Left Join • pd.merge( df1, df2, on=['CODE'], how='right') • 오른쪽 DataFrame의 다른 열 값들을 보존하며 왼쪽 DataFrame을 끼워 맞춘다. • df2.CODE의 전체를 보존하며 병합, df1.CODE에서 없는 것들은 NaN으로 채움 CODE NAME 0 A 아 1 B 비 2 C 씨 3 D 디 4 E 이 CODE VALUE 0 A 1 1 B 2 2 C 3 3 X 4 4 Y 5 CODE NAME VALUE 0 A 아 1 1 B 비 2 2 C 씨 3 3 X NaN 4 4 Y NaN 5 df1 df2 + = rf
  • 77. code1 = {'CODE':['A','B','C','D','E'], 'NAME':['아','비','씨','디','이']} code2 = {'CODE' :['A','B','C','X','Y'], 'VALUE':['1','2','3','4','5']} df1 = pd.DataFrame.from_dict(code1) df2 = pd.DataFrame.from_dict(code2) rf = pd.merge(df1, df2, on=['CODE'], how='outer') Pandas Merge - Outer Join • pd.merge( df1, df2, on=['CODE'], how='outer') • 두 개의 DataFrame의 기준 칼럼의 합집합 기준으로 병합 • 서로 없는 CODE 값들에 해당되는 다른 칼럼들은 NaN으로 채움 CODE NAME 0 A 아 1 B 비 2 C 씨 3 D 디 4 E 이 CODE VALUE 0 A 1 1 B 2 2 C 3 3 X 4 4 Y 5 df1 df2 + = rf CODE NAME VALUE 0 A 아 1 1 B 비 2 2 C 씨 3 3 D 디 NaN 4 E 이 NaN 5 X NaN 4 6 Y NaN 5
  • 78. Pandas 그룹화 연산 • groupby(['칼럼명',…]) • '칼럼명' 내의 고유 값 기준으로 Groupby 객체 리턴 • 보통 groupby 메소드에 지정된 칼럼명은 인덱스로 지정됨 • Groupby 객체에는 그룹별로 연산을 할 수 있는 그룹 연산 메서드 존재 • Groupby 그룹 연산 메소드 • size(), count() : 갯수 • mean(), median(), min(), max() : 평균, 중앙값, 최소, 최대 • sum(), prod(), std(), var(), quantile() : 합계, 곱, 표준편차, 분산, 사분위수 df = pd.DataFrame(np.array([100,20000, 50,50000, 90, 50000]).reshape(3,2), columns=['성능','가격']) df.groupby('성능').sum() df.groupby('성능').mean() df.groupby('성능').count() 가격 성능 70 70000 90 50000 가격 성능 70 35000 90 50000 가격 성능 70 2 90 1
  • 80. (1) 하루 승인 거래 건수 분석 • trns_1day_series 파일 : SEND, RECV, APPROVAL, REJECT 기준으로 1분당 거래 건수 • 거래 갭 건수, 거절율, 승인거래 회귀분석 데이터 분석 df = pd.read_csv('trns_1day_series') df.head() #데이터 최초 5개 샘플 추출 df.describe() # 데이터 구성이 숫자일 때, DataFrame 구성 현황을 간략히 설명 SEND RECV APPROVAL REJECT 0 4779 5045 4024 755 1 5103 5055 4196 907 2 5035 5073 4653 382 3 4757 4762 4530 227 4 4639 4664 4425 214 SEND RECV APPROVAL REJECT count 1440 1440 1440 1440 mean 10274.083 10274.832 10062.035 212.04792 std 6683.457 6683.4421 6584.3905 135.07823 min 769 769 714 16 25% 3580.75 3579.25 3469 84 50% 11115 11133.5 10901.5 210.5 75% 15745 15729.25 15451 305 max 24859 24911 24565 907 SEND,RECV,APPROVAL,REJECT 4779,5045,4024,755 5103,5055,4196,907 5035,5073,4653,382 4757,4762,4530,227 ….. trns_1day_series 내용
  • 81. (1) 하루 승인 거래 건수 분석 # 24시간을 분으로 나누면 1440 구간 len(df) Out[]: 1440 #1분 단위로 시간 리스트를 생성할 경우 1min #1시간 단위로 시간 리스트 생성할 경우 1h #1초 단위로 시간 리스트를 생성할 경우 1s pd.date_range('00:00', '23:59', freq='1min') Out[]: array([datetime.time(0, 0), datetime.time(0, 1), datetime.time(0, 2), ..., datetime.time(23, 57), datetime.time(23, 58), datetime.time(23, 59)], dtype=object) df['TIME'] = pd.date_range('00:00', '23:59', freq='1min') df = df.set_index('TIME') # 인덱스로 지정 SEND RECV APPROVAL REJECT TIME 0:00:00 4779 5045 4024 755 0:01:00 5103 5055 4196 907 0:02:00 5035 5073 4653 382 0:03:00 4757 4762 4530 227 0:04:00 4639 4664 4425 214
  • 82. (1) 하루 승인 거래 건수 분석 # 거래 SEND, RECV 갭 차이 df['GAP'] = np.abs ( df.SEND - df.RECV ) df.plot(y='GAP') # df[['GAP']].plot() 결과는 동일 # 거래 거절율 계산 df['REJECT_AVG'] = df.REJECT / (df.APPROVAL + df.REJECT) * 100 df.plot(y='REJECT_AVG') SEND RECV APPROVAL REJECT GAP REJECT_AVG TIME 0:00:00 4779 5045 4024 755 266 15.798284 0:01:00 5103 5055 4196 907 48 17.773859 0:02:00 5035 5073 4653 382 38 7.586892 0:03:00 4757 4762 4530 227 5 4.771915 0:04:00 4639 4664 4425 214 25 4.613063 SEND RECV APPROVAL REJECT GAP TIME 0:00:00 4779 5045 4024 755 266 0:01:00 5103 5055 4196 907 48 0:02:00 5035 5073 4653 382 38 0:03:00 4757 4762 4530 227 5 0:04:00 4639 4664 4425 214 25
  • 83. (1) 하루 승인 거래 건수 분석 # 선형 회귀분석선 계산 len(df) Out[]: 1440 np.arange(0, len(df)) Out[]: array([ 0, 1, 2, ..., 1437, 1438, 1439]) np.array(df.APPROVAL) Out[]: array([4024, 4196, 4653, ..., 5006, 4935, 4940], dtype=int64) fp = np.polyfit( np.arange(0, len(df)), np.array(df.APPROVAL), 8) # 8차 다항식 계수 추출 fd = np.poly1d(fp) # 다항식 함수 생성 df['REGRESSION'] = fd( np.arange(0, len(df)) ) # 회귀분석 데이터 df.plot(y=['APPROVAL','REGRESSION']) # 승인거래, 회귀분석선 출력
  • 84. (1) 하루 승인 거래 건수 분석 회귀분석 평가 방법 # MSE 계산 ((df.APPROVAL - df.REGRESSION) **2).sum() / 1440 # 오차의 제곱 (**2)을 합계(sum)을 낸 이후 나누기 Out[]: 2289273.5327607947 ((df.APPROVAL - df.REGRESSION) **2).mean() # 오차 제곱에 대한 평균 함수 Out[]: 2289273.5327607947 # RMSE 계산 mse = ((df.APPROVAL - df.REGRESSION) **2).mean() rmse = np.sqrt(mse) rmse, mse Out[]: (1513.0345444704144, 2289273.5327607947) 𝑦𝑡 𝑦𝑖 𝑦 𝑥 오차𝑒𝑖 손실함수(Loss function) 예상과 실측의 정답에 대한 오류를 하나의 숫자로 나타냄 정답에 가까우면 작은 값, 오답에 가까우면 큰 값 MSE(Mean Square Error) : 오차를 제곱한 것에 대한 평균 1 𝑛 ෍ 𝑖=1 (𝑦𝑖 − 𝑦𝑡)2 RMSE(Root Mean Square Error) : MSE에 제곱근 𝑀𝑆𝐸 = 1 𝑛 σ𝑖=1(𝑦𝑖 − 𝑦𝑡)2
  • 85. (1) 하루 승인 거래 건수 분석 # 손실을 줄이기 위해 시간별 회귀분석선 재구현 # 1분당 거래이므로 60개 거래 실측값 * 24시간으로 2차원 배열 변환 hh_list = np.array( df.APPROVAL ).reshape(24, 60) Out[]: array([[ 4024, 4196, 4653, ..., 3684, 3586, 3576], [ 3507, 3689, 3542, ..., 2501, 2360, 2340], [ 2058, 2010, 1858, ..., 1162, 1174, 1222], ..., [13822, 13825, 13903, ..., 10940, 10827, 10839], [10824, 10834, 10665, ..., 7589, 7378, 7470], [ 7482, 7307, 7314, ..., 5006, 4935, 4940]], dtype=int64) hh_list.shape Out[]: (24, 60) reg_list = [] for mm_list in hh_list: # 2차원 배열 리스트에 대한 배열 리스트 추출 x = np.arange(0, 60) # [0,…,59] 60개짜리 X축 배열 생성 y = mm_list # 60개짜리 실측값 Y축 배열 생성 fp = np.polyfit(x, y, 4) # 4차 다항식 계수 연산 fn = np.poly1d(fp) # 1차원 다항 함수 생성 reg_list.append(fn(x)) # 다항함수에 의한 회귀분석 데이터 생성 df['REGRESSION_H'] = np.array(reg_list).flatten() # 회귀분석 데이터를 1차원 리스트로 차원 축소 삽입 df.plot(y=['REGRESSION', 'REGRESSION_H']) # 기존 회귀분석, 신규 회귀분석 차트 출력
  • 86. (2) 전문 거래 로그 분석 • 전문 거래들에 대한 로그들을 활용한 전문별 처리 시간 및 거래 현황 분석 • trns_msg_log 파일 : 전문에 대한 거래에 대한 로그 • {전송방향코드, 전문번호, 시간, 처리결과코드, 기관코드, 거래고유번호} 구성 • 데이터 구분자는 콜롬 (:) • trns_firm_info 파일 : 기관코드별 기관명 (CSV 파일) • trns_msg_info 파일 : 전문번호별 전문명 (CSV 파일) • trns_msg_resp_code_info 파일 : 처리결과코드별 사유명 (CSV파일) TRNS:MSG_CODE:TIME:RESP_CODE:FIRM_CODE:SEQ 1:0100:133000: :03:2e65c202e525e90e1d95 1:0300:133000: :48:802407d045fa5d1a8287 1:0200:133000: :03:a1d3e524e4751b450a20 1:0200:133000: :11:ed976e8de9708d167a64 1:9300:133000: :03:b7a878a4ff5d3076dd4b 1:0400:133000: :72:325d06919857f7f20761 1:0200:133000: :72:b07ecc97fbb154ac7373 2:9310:133000:00:20:ec1109dd984d711d4280 1:9300:133000: :20:ec1109dd984d711d4280 ………
  • 87. (2) 전문 거래 로그 분석 코드 데이터 정보 매핑 # 전문 로그 데이터 DataFrame으로 생성 log_df = pd.read_csv('trns_msg_log/trns_msg_log', sep=':', dtype=str) # 전문코드 DataFrame생성, dtype을 지정한 이유는 전문번호를 숫자로 인식하여 0100이 100으로 변환되는 것을 막기 위함 msg_df = pd.read_csv('trns_msg_log/trns_msg_info', dtype=str) TRNS MSG_CODE TIME RESP_CODE FIRM_CODE SEQ 0 1 0100 133000 03 2e65c202e525e90e1d95 1 1 0300 133000 48 802407d045fa5d1a8287 2 1 0200 133000 03 a1d3e524e4751b450a20 3 1 0200 133000 11 ed976e8de9708d167a64 4 1 9300 133000 03 b7a878a4ff5d3076dd4b 5 1 0400 133000 72 325d06919857f7f20761 6 1 0200 133000 72 b07ecc97fbb154ac7373 7 2 9310 133000 00 20 ec1109dd984d711d4280 8 1 9300 133000 20 ec1109dd984d711d4280 9 1 0420 133000 72 f24a35eca38fd37b698c MSG_CODE MSG_NAME 0 0100 MS승인요청 1 0110 MS승인응답 2 0300 IC승인 요청 3 0310 IC승인 응답 4 0420 MS승인취소 요청
  • 88. (2) 전문 거래 로그 분석 코드 데이터 정보 매핑 # 기관코드(FIRM_CODE)에 해당되는 정보 DataFrame 생성 firm_df = pd.read_csv('trns_msg_log/trns_firm_info', dtype=str) # 응답코드(RESP_CODE)에 해당되는 정보 DataFrame 생성 resp_df = pd.read_csv('trns_msg_log/trns_msg_resp_code_info', dtype=str) # 4개의 DataFrame 생성이 완료되었으면 본격적으로 데이터 전처리 시작 FIRM_CODE FIRM_NAME 0 03 IBK기업은행 1 11 NH농협은행 2 20 우리카드 3 23 SC제일은행 4 48 새마을금고 RESP_CODE RESP_NAME 0 00 정상 1 01 정상 2 60 거래정지카드 3 63 분실도난카드 4 K2 유효검증오류 5 Z1 시스템장애
  • 89. (2) 전문 거래 로그 분석 코드 데이터 정보 매핑 # DataFrame Merge tf1 = pd.merge(log_df, msg_df, on=['MSG_CODE'], how='left') # 전문번호 정보 병합 tf2 = pd.merge(tf1 , firm_df, on=['FIRM_CODE'], how='left') # 기관코드 정보 병합 tf3 = pd.merge(tf2 , resp_df, on=['RESP_CODE'], how='left') # 응답코드 정보 병합 # 송수신 구분자에 대한 변경 tf3.loc[tf3.TRNS == '1', 'TRNS'] = 'SEND' # tf3.TRNS=='1'인 열들을 모두 선택 후 TRNS 칼럼 값으로 'SEND' tf3.loc[tf3.TRNS == '2', 'TRNS'] = 'RECV' # tr3.TRNS=='2'인 열들을 모두 선택 후 TRNS 칼럼 값으로 'RECV' TRNS MSG_CODE TIME RESP_CODE FIRM_CODE SEQ MSG_NAME FIRM_NAME RESP_NAME 0 SEND 0100 133000 03 2e65c202e525e90e1d95 MS승인요청 IBK기업은행 NaN 1 SEND 0300 133000 48 802407d045fa5d1a8287 IC승인 요청 새마을금고 NaN 2 SEND 0200 133000 03 a1d3e524e4751b450a20 현금서비스 요청 IBK기업은행 NaN 3 SEND 0200 133000 11 ed976e8de9708d167a64 현금서비스 요청 NH농협은행 NaN 4 SEND 9300 133000 03 b7a878a4ff5d3076dd4b 기타승인 요청 IBK기업은행 NaN 5 SEND 0400 133000 72 325d06919857f7f20761 IC승인취소 요청 우체국 NaN 6 SEND 0200 133000 72 b07ecc97fbb154ac7373 현금서비스 요청 우체국 NaN 7 RECV 9310 133000 00 20 ec1109dd984d711d4280 기타승인 응답 우리카드 정상 8 SEND 9300 133000 20 ec1109dd984d711d4280 기타승인 요청 우리카드 NaN 9 SEND 0420 133000 72 f24a35eca38fd37b698c MS승인취소 요청 우체국 NaN
  • 90. (2) 전문 거래 로그 분석 전문 처리시간 및 거래 현황 # 로그 거래 원본 데이터에서 SEND와 RECV 기준으로 두 개 DataFrame으로 분리 send_df = log_df[log_df.TRNS==1'] recv_df = log_df[log_df.TRNS =='2'] # 기관코드(FIRM_CODE)와 거래고유번호(SEQ)를 기준으로 병합 tf = pd.merge(send_df, recv_df, on=['FIRM_CODE', 'SEQ'], how='outer') #필요한 칼럼만 필터링 후 해당 칼럼들에 대한 칼럼명 변경 tf = tf [['SEQ', 'FIRM_CODE', 'MSG_CODE_x', 'TIME_x', 'TIME_y','RESP_CODE_y']] tf = tf.rename(columns={'MSG_CODE_x':'MSG_CODE', 'TIME_x':'SEND_TIME', 'TIME_y':'RECV_TIME', 'RESP_CODE_y':'RESP_CODE'}) TRNS_x MSG_CODE_x TIME_x RESP_CODE_x FIRM_CODE SEQ TRNS_y MSG_CODE_y TIME_y RESP_CODE_y 0 1 0100 133000 03 2e65c202e525e90e1d95 2 0110 133005 01 1 1 0300 133000 48 802407d045fa5d1a8287 2 0310 133001 01 2 1 0200 133000 03 a1d3e524e4751b450a20 2 0210 133000 01 3 1 0200 133000 11 ed976e8de9708d167a64 2 0210 133008 00 4 1 9300 133000 03 b7a878a4ff5d3076dd4b 2 9310 133003 01 SEQ FIRM_CODE MSG_CODE SEND_TIME RECV_TIME RESP_CODE 0 2e65c202e525e90e1d95 03 0100 133000 133005 01 1 802407d045fa5d1a8287 48 0300 133000 133001 01 2 a1d3e524e4751b450a20 03 0200 133000 133000 01 3 ed976e8de9708d167a64 11 0200 133000 133008 00 4 b7a878a4ff5d3076dd4b 03 9300 133000 133003 01
  • 91. (2) 전문 거래 로그 분석 전문 처리시간 및 거래 현황 # 처리시간 계산 # SEND_TIME과 RECV_TIME은 문자열이므로 시간 GAP 계산을 위한 포멧 변환 필요 # pd.to_datetime 함수를 이용하면 쉽게 칼럼들에 대한 값을 datetime 객체들로 변환 tf['S_DATETIME'] = pd.to_datetime(tf.SEND_TIME, format='%H%M%S') tf['R_DATETIME'] = pd.to_datetime(tf.RECV_TIME, format='%H%M%S') tf['TIME_GAP'] = tf.R_DATETIME - tf.S_DATETIME # 이제 불필요한 칼럼 제거 tf = tf.drop(['S_DATETIME','R_DATETIME'], axis=1) SEQ FIRM_CODE MSG_CODE SEND_TIME RECV_TIME RESP_CODE TIME_GAP 0 2e65c202e525e90e1d95 03 0100 133000 133005 01 00:00:05 1 802407d045fa5d1a8287 48 0300 133000 133001 01 00:00:01 2 a1d3e524e4751b450a20 03 0200 133000 133000 01 00:00:00 3 ed976e8de9708d167a64 11 0200 133000 133008 00 00:00:08 4 b7a878a4ff5d3076dd4b 03 9300 133000 133003 01 00:00:03 5 325d06919857f7f20761 72 0400 133000 133002 01 00:00:02 6 b07ecc97fbb154ac7373 72 0200 133000 133008 00 00:00:08 7 ec1109dd984d711d4280 20 9300 133000 133000 00 00:00:00 8 f24a35eca38fd37b698c 72 0420 133000 133005 00 00:00:05 9 77b06c0cd73f42998019 11 9300 133000 133006 00 00:00:06
  • 92. (2) 전문 거래 로그 분석 전문 처리시간 및 거래 현황 # 처리시간별 현황 tf.groupby('TIME_GAP').count() # 처리시간 그룹 후 칼럼별 ROW의 건수 tf.groupby('TIME_GAP').count().rename(columns={'SEQ':'COUNT'}) # 처리시간 그룹연산 처리 후 SEQ 칼럼명 변경 tf.groupby('TIME_GAP').count().rename(columns={'SEQ':'COUNT'}) [['COUNT']] # COUNT 칼럼만 선택 # 차트 출력 df = tf.groupby('TIME_GAP').count().rename(columns={'SEQ':'COUNT'}) [['COUNT']] df.plot(kind='bar') COUNT TIME_GAP 0:00:00 91 0:00:01 96 0:00:02 112 0:00:03 96 0:00:04 99 0:00:05 106 0:00:06 99 0:00:07 94 0:00:08 104 0:00:09 103
  • 93. (2) 전문 거래 로그 분석 전문 처리시간 및 거래 현황 #그룹화 칼럼을 2개로 지정했을 경우 # 기관코드, 전문번호 그룹화한 건수 tf.groupby(['FIRM_CODE','TIME_GAP']).count() tf.groupby(['FIRM_CODE','TIME_GAP']).count().rename(columns={'SEQ':'COUNT'}) tf.groupby(['FIRM_CODE','TIME_GAP']).count().rename(columns={'SEQ':'COUNT'}) [['COUNT']] df = tf.groupby(['FIRM_CODE', 'TIME_GAP']).count().rename(columns={'SEQ':'COUNT'}) [['COUNT']] df.plot(kind='bar', figsize=(15,4)) #bar 차트, 차트의 크기는 (15, 4)
  • 94. (2) 전문 거래 로그 분석 전문 처리시간 및 거래 현황 # 기관코드별 전분번호의 처리 시간 MAX, MIN (초) 분석 zf = tf[['FIRM_CODE','MSG_CODE','TIME_GAP']] # 3개 칼럼만 선택한 DataFrame 생성 max_df = zf.groupby(['FIRM_CODE','MSG_CODE']).max().rename(columns={'TIME_GAP':'MAX_GAP'}) min_df = zf.groupby(['FIRM_CODE','MSG_CODE']).min().rename(columns={'TIME_GAP':'MIN_GAP'}) max_df = max_df.reset_index() #그룹연산으로 지정된 index를 reset (merge를 위하여) min_df = min_df.reset_index() #그룹연산으로 지정된 index를 reset df = pd.merge(max_df, min_df) df['MAX_GAP'] = df.MAX_GAP.dt.seconds # timedelta 객체를 seconds로 변환 (정수형 값) df['MIN_GAP'] = df.MIN_GAP.dt.seconds # timedelta 객체를 seconds로 변환 (정수형 값) df.set_index(['FIRM_CODE','MSG_CODE']).plot(kind='bar', figsize=(10,5)) # 차트 출력
  • 96. Matplotlib 기초 개념 • Matplotlib • 산업계, 교육계에서 널리 사용되고 있는 수치 해석 소프트웨어 • 2차원 데이터를 시각화하기 위한 패키지 • MATLAB과 유사한 사용자 인터페이스 • 그래프의 종류, 축, 눈금선 그래프 이름 등 그림 요소의 상세한 서식 설정 가능 • 다양한 출력 형식(PNG,SVG,JPG 등)으로 저장 가능 %matplot inline import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) data = [0, 1] ax.plot(data) plt.show()
  • 97. Matplotlib Figure와 Subplot • 핵심 개념 : Figure와 Subplot Figure Subplot (Axes) Subplot (Axes) Figure 서브 플롯 (그래프영역) 작성 하는 틀 Subplot 그래프를 작성하기 위한 영역 Axes Figure 안의 (Sub)Plot들은 각각의 Axes 객체 속함 Axis 플롯의 가로 축이나 세로 축을 의미 Axis Axis
  • 98. Matplotlib Figure와 Subplot • add_subplot() 메소드 • add_subplot(지정위치 값)에서 지정위치 값은 3자리 숫자 • 지정위치 값은 순서대로 [총 행수], [총 열수], [서브플롯 번호] 의미 import matplotlib.pyplot as plt fig = plt.figure() ax1 = fig.add_subplot(221) #2행 2열 1번 ax2 = fig.add_subplot(222) #2행 2열 2번 ax3 = fig.add_subplot(223) #2행 2열 3번 ax1.text(.2, .5, 'ax1(221)', fontsize=15) ax2.text(.2, .5, 'ax2(222)', fontsize=15) ax3.text(.2, .5, 'ax3(223)', fontsize=15) plt.show()
  • 99. Matplotlib Figure와 Subplot • add_subplot() 메소드 • add_subplot(지정위치 값)에서 지정위치의 3자리 숫자를 콤마(,)로 를 구분 가능 • add_subplot([총 행수], [총 열수], [서브플롯 번호]) 가능 import matplotlib.pyplot as plt fig = plt.figure() ax1 = fig.add_subplot(2,2,1) #2행 2열 1번 ax2 = fig.add_subplot(2,2,2) #2행 2열 2번 ax3 = fig.add_subplot(2,2,3) #2행 2열 3번 ax1.plot([0,1]) # Y축값 (0, 1) ax2.plot([1,0]) # Y축값 (1, 0) ax3.plot([1,1]) # Y축값 (1, 1) plt.show()
  • 100. Matplotlib Figure와 Subplot • subplots() 메소드 • pyplot.subplots() 메소드를 이용해 Figure 생성과 Subplot 배치를 동시 설정 • pyplot.subplots() 메소드의 리턴 값은 figure와 axes 객체 배열 • axes[열 인덱스, 행 인덱스] • 인덱스는 0부터 시작하는 점을 참고 import matplotlib.pyplot as plt fig, axes = plt.subplots(2, 2) #2x2 Axes 배열 생성 axes[0, 0].plot([0,1]) # Y축값 (0, 1) axes[0, 1].plot([1,0]) # Y축값 (1, 0) axes[1, 0].plot([1,1]) # Y축값 (1, 1) plt.show()
  • 101. Matplotlib 꺾은선 그래프 • Axes.plot([x], y, [fmt], data=None, **kwargs) 메소드 • plot() 메소드의 파라미터가 하나일 경우 Y 값으로 설정되고, X 값은 자동적으로 지정 • plot() 메소드에 사용되는 데이터형 • 파이썬 기본 1차원 구조체(리스트, 튜플) • numpy.ndarray • pandas.Series import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) x = [0, 2, 4] y = [0, 4, 2] ax.plot(x, y) plt.show()
  • 102. Matplotlib 꺾은선 그래프 • 여러 개의 선을 그리는 경우 • 1개의 서브플롯에 여러 개의 그래프를 그릴 수 있음 • Axes 객체에 plot()을 여러 번 호출 import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) x = [0, 1, 2] y1 = [0, 4, 3] y2 = [3, 2, 0] ax.plot(x, y1) ax.plot(x, y2) plt.show()
  • 103. Matplotlib 꺾은선 그래프 • 하루치 거래 승인 꺾은선 그래프 • pandas의 Series를 지정하여 그리기 import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv('trns_1day_series') fig = plt.figure(figsize=(10, 4)) # 그래프 크기 ax = fig.add_subplot(111) ax.plot(df.index, df.APPROVAL, label='승인') # 승인건수 ax.plot(df.index, df.REJECT , label='거절') # 거절건수 ax.set_title('1일 거래 건수 현황') # 차트 타이틀 ax.set_ylabel('건수') # Y축 레이블 ax.set_xlabel('시간') # X축 레이블 #범례 유호화 ax.legend() plt.show()
  • 104. Matplotlib 차트 한글 폰트 지정 • 맑은 고딕체 폰트 확인 from matplotlib import rcParams rcParams['font.sans-serif']= 'Malgun Gothic' rcParams['font.weight'] = 'regular' rcParams['axes.titlesize'] = 15 rcParams['ytick.labelsize'] = 12 rcParams['xtick.labelsize'] = 12 import matplotlib.font_manager as fm font_list = fm.findSystemFonts(fontpaths=None, fontext='ttf') [(f.name, f.fname) for f in fm.fontManager.ttflist if 'Malgun' in f.name] Out[]: [('Malgun Gothic', 'C:WindowsFontsmalgun.ttf'), ('Malgun Gothic', 'C:WindowsFontsmalgunsl.ttf'), ('Malgun Gothic', 'C:WindowsFontsmalgunbd.ttf')] • 맑은 고딕체 폰트 지정
  • 105. Matplotlib 꺾은선 그래프 • 그래프 스타일 적용 옵션 • linestyle = solid, dashed, dotted, dashdotted 등 그래프 선의 형태 • color = black, grey, red, blue 등 그래프의 색깔 • marker = o , >, ^ 등 좌표에 해당하는 값 부분을 표시하는 마커 color linestyle
  • 106. Matplotlib 꺾은선 그래프 • 그래프 스타일 적용 • color = 'r' 대표 16색에 대해서는 앞글자 1개만 지정해도 됨 • linestyle = 'dashed' 선의 스타일을 결정 • marker = 'o' 마커의 타입을 결정 import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) x = [0, 1, 2] y1 = [0, 4, 3] y2 = [3, 2, 0] ax.plot(x, y1, color='g', linestyle='dashed', marker='o') ax.plot(x, y2, color='r', linestyle='dotted', marker='^') plt.show()
  • 107. Matplotlib 꺾은선 그래프 • 하루치 거래 승인 꺾은선 그래프 • 선 그래프의 스타일 적용 import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv('trns_1day_series') fig = plt.figure(figsize=(10, 4)) ax = fig.add_subplot(111) ax.plot(df.index, df.APPROVAL, label='승인', linestyle='dotted', c='g') # 승인건수 ax.plot(df.index, df.REJECT , label='거절', linestyle='dashed', c='r') # 거절건수 ax.set_title('1일 거래 건수 현황') # 차트 타이틀 ax.set_ylabel('건수') # Y축 레이블 ax.set_xlabel('시간') # X축 레이블 #범례 유호화 ax.legend() plt.show()
  • 108. Matplotlib 막대 그래프 • Axes.bar(*args, data=None, **kwargs) 메소드 • 막대 그래프는 수량을 막대의 길이로 나타낸 그래프 • 파라미터로 X, Y 값을 지정 • tick_label = [] 에서 배열 인자로 눈금에 대한 레이블 지정 가능 import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) x = [1, 2] y = [3, 5] labels = ['A', 'B'] ax.bar(x, y, tick_label=labels) plt.show()
  • 109. Matplotlib 막대 그래프 • Axes.barh(*args, data=None, **kwargs) 메소드 • 막대 그래프를 수평으로 나타내도록 한다. • 입력 값은 bar() 메소드와 동일 import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) x = [1, 2] y = [3, 5] labels = ['A', 'B'] ax.barh(x, y, tick_label=labels) plt.show()
  • 110. Matplotlib 막대 그래프 • 실패한 막대 그래프의 그룹화 • 여러 번의 Axes.bar(x, y) 호출에서 X 좌표 위치가 동일할 경우 덮어 씌워짐 • BAR 차트에서 데이터 그룹화를 위해서는 표현을 위한 전략 필요 import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv('trns_1day_series') df.mean() Out[]: SEND 10274.082639 RECV 10274.831944 APPROVAL 10062.034722 REJECT 212.047917 dtype: float64 s_mean, s_max = df.mean() , df.max() fig = plt.figure() ax = fig.add_subplot(111) ax.bar([1,2,3,4], s_mean, label='평균') #X축 좌표 = [1,2,3,4] ax.bar([1,2,3,4], s_max , label='최대') #X축 좌표 = [1,2,3,4] plt.show()
  • 111. Matplotlib 막대 그래프 • 데이터를 각각 표현하는 방법 • '평균' 데이터들의 좌표를 1씩 공간을 만들고, 그 사이에 '최대' 데이터들을 위치 • '평균' 데이터들의 X좌표 = [1,3,5,7] • '최대' 데이터들의 X좌표 = [2,4,6,8] import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv('trns_1day_series') s_mean, s_max = df.mean() , df.max() fig = plt.figure() ax = fig.add_subplot(111) ax.bar([1,3,5,7], s_mean, label='평균') ax.bar([2,4,6,8], s_max, label='최대') ax.legend() plt.show() 서로 X 축의 좌표를 침범하지 않게 한다
  • 112. Matplotlib 막대 그래프 • 같은 인덱스는 붙이고, 다른 인덱스는 멀리. • 두 '평균' 데이터, '최대' 데이터의 X좌표는 각각 1, 2부터 시작 • 차트 폭(width)을 1로 지정하여 '평균'과 '최대' 그래프를 붙임 • 각각의 X좌표는 3씩 증가시키면 인덱스별 분류가 좀더 쉽게 인식 import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv('trns_1day_series') s_mean, s_max = df.mean() , df.max() fig = plt.figure() ax = fig.add_subplot(111) ax.bar([1,4,7,10], s_mean, width=1, label='평균') ax.bar([2,5,8,11], s_max, width=1, label='최대') ax.legend() plt.show() 남은 문제 - 레이블을 카테고리화를 시켜야 한다.
  • 113. Matplotlib 막대 그래프 • X 축의 레이블 표시 기준 변경 • 각 데이터셋은 4가지 데이터 기준으로 표현 (SEND, RECV, APPROVAL, REJECT) • X좌표에 분류된 데이터 중심 값을 4개 지정하여 표시 • set_xticks([X축 값1, X축 값2,…,… ]) : 여기에 지정된 X축 값만 레이블로 나타남 import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv('trns_1day_series') s_mean, s_max = df.mean() , df.max() fig = plt.figure() ax = fig.add_subplot(111) ax.bar([1,3,5,7], s_mean, label='평균') ax.bar([2,4,6,8], s_max, label='최대') ax.set_xticks([1.5, 4.5, 7, 11]) ax.legend() plt.show()
  • 114. Matplotlib 막대 그래프 • X좌표의 레이블 카테고리 값 지정 • X좌표의 tick 값을 숫자가 아닌 카테고리 지정 값으로 변경 • set_xticklabels([카테고리 값1, 카테고리 값2, …, ]) • set_xticks() 메소드가 먼저 호출된 이후 지정되어야 함 import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv('trns_1day_series') s_mean, s_max = df.mean() , df.max() fig = plt.figure() ax = fig.add_subplot(111) ax.bar([1,3,5,7], s_mean, label='평균') ax.bar([2,4,6,8], s_max, label='최대') ax.set_xticks([1.5, 4.5, 7, 11]) ax.set_xticklabels(['SEND','RECV','APPROVAL','REJECT']) ax.legend() plt.show()
  • 115. Matplotlib 두 개 축을 가진 그래프 • 두 개의 Y축 기준을 나타내는 그래프 • Y 축을 LEFT 사이드와 RIGHT 사이드로 2개 축 지정 • twinx() : X 축의 기준을 공유하여 2개 Y축을 가질 경우 • twiny() : Y 축의 기준을 공유하여 2개 X축을 가질 경우 fig = plt.figure(figsize=(10, 4)) ax1 = fig.add_subplot(111) ax2 = ax1.twinx() # X축 공유하는 Y축 분리 ax1.plot(df.index, df.APPROVAL, label='승인', color='green') ax2.bar(df.index, df.REJECT , label='거절', color='purple' ) ax1.set_title('1일 거래 건수 현황') ax1.set_ylabel('승인 건수') #Y1축 레이블 ax2.set_ylabel('거절 건수') #Y2축 레이블 ax1.set_xlabel('시간') ax1.legend(loc=2) #범례 위치 지정 ax2.legend(loc=1) #범례 위치 지정 plt.show()
  • 116. Matplotlib 산점도 그래프 • 점(scatter) 그래프 • Axes.scatter(x, y, …) 메소드 사용 • X축과 Y축에 수량이나 크기 등을 표시하기 위해 적합 • 일반적으로 데이터 분포 상황을 확인할 때 많이 활용 fig = plt.figure(figsize=(10, 4)) ax1 = fig.add_subplot(111) ax2 = ax1.twinx() # X축 공유하는 Y축 분리 ax1.plot(df.index, df.APPROVAL, label='승인', color='green') ax2.scatter(df.index, df.REJECT , label='거절', color='purple' ) ax1.set_title('1일 거래 건수 현황') ax1.set_ylabel('승인 건수') #Y1축 레이블 ax2.set_ylabel('거절 건수') #Y2축 레이블 ax1.set_xlabel('시간') ax1.legend(loc=2) #범례 위치 지정 ax2.legend(loc=1) #범례 위치 지정 plt.show()
  • 117. Matplotlib 원 그래프 • 원(circle) 그래프 • Axes.pie(x, labels=[], …) 메소드 사용 • 배열 X는 필수, labels 와 같은 옵션들에 의해 스타일이 결정 from matplotlib import rcParams import matplotlib.pyplot as plt import pandas as pd import numpy as np rcParams['font.sans-serif']= 'Malgun Gothic' rcParams['font.weight'] = 'regular' rcParams['axes.titlesize'] = 15 rcParams['ytick.labelsize'] = 12 rcParams['xtick.labelsize'] = 12 fig = plt.figure(figsize=(5, 5)) ax = fig.add_subplot(111) label_list = ['승인','입금','제휴'] dataset = [50, 100, 30] ax.pie(dataset, labels=label_list) plt.show()
  • 118. Seaborn 기초 개념 • 시각화와 통계 기능을 보다 편리하게 제공 • 시각화 기능은 Matplotlib 패키지를 기반으로 개발되어 편리한 시각화 기능 • 통계적 기능은 Statsmodel 패키지를 기반으로 개발되어 편리한 분석 기능 • 샘플 데이터를 제공하여 교육용 데이터가 풍부하게 제공 • 단순 그래프부터 히트맵까지 다양한 시각화 기능 제공함 import matplotlib.pyplot as plt import pandas as pd import seaborn as sns df = pd.read_csv('trns_1day_series') df.describe() sns.boxplot(data=df) #박스플롯으로 표시 SEND RECV APPROVAL REJECT count 1440 1440 1440 1440 mean 10274.083 10274.832 10062.035 212.04792 std 6683.457 6683.4421 6584.3905 135.07823 min 769 769 714 16 25% 3580.75 3579.25 3469 84 50% 11115 11133.5 10901.5 210.5 75% 15745 15729.25 15451 305 max 24859 24911 24565 907
  • 119. Seaborn 박스 플롯 • 카테고리 기준으로 데이터 변화를 표현할 때 유리 • 표현할 때는 카테고리를 명확하게 구분 지어야 함 • 어떤 기준으로 데이터의 수치를 표현할지! • 카테고리 기준은 hue 옵션에 지정하면 됨 (hue 사용 시 X축, Y축 기준은 필수) df = pd.read_csv('titanic.csv', sep='t') df.head() sns.boxplot(x='Survived', y='Age', hue='Sex', data=df) #성별 기준으로, 생존여부 기준으로 나이 분포 PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked 0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 NaN S 1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38 1 0 PC 17599 71.2833 C85 C 2 3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 NaN S 3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S 4 5 0 3 Allen, Mr. William Henry male 35 0 0 373450 8.05 NaN S
  • 120. Seaborn 박스 플롯 #기관코드별 정상(APPROVAL)/거절(REJECT) 처리시간 분포 시각화 df = pd.read_csv('trns_msg_log/trns_msg_log', sep=':', dtype=str) #거래 로그 DataFrame s_df = df[df.TRNS == '1'] #SEND 거래 r_df = df[df.TRNS == '2'] #RECV 거래 tf = pd.merge(s_df, r_df, on=['FIRM_CODE','SEQ']) tf['APPROVAL'] = tf.RESP_CODE_y.isin(['00','01']) #정상 여부 # SEND와 RECV 전문 처리시간 tf['S_DATETIME'] = pd.to_datetime(tf.TIME_x, format='%H%M%S') tf['R_DATETIME'] = pd.to_datetime(tf.TIME_y, format='%H%M%S') tf['TIME_GAP'] = tf.R_DATETIME - tf.S_DATETIME tf['TIME_GAP'] = tf.TIME_GAP.dt.seconds #시간을 초 단위 정수로 변환 #승인/거절 카테고리 기준으로, 기관별 처리시간 분포 sns.boxplot(x='FIRM_CODE', y='TIME_GAP', hue='APPROVAL', data=tf)
  • 121. Seaborn 박스 플롯 • 카테고리 기준으로 데이터 변화를 표현할 때 유리 • 표현할 때는 카테고리를 명확하게 구분 지어야 함 • 어떤 기준으로 데이터의 수치를 표현할지! • 카테고리 기준은 hue 옵션에 지정하면 됨 (hue 사용 시 X축, Y축 기준은 필수) df = pd.read_csv('titanic.csv', sep='t') df.head() sns.boxplot(x='Survived', y='Age', hue='Sex', data=df) #성별 기준으로, 생존여부 기준으로 나이 분포 PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked 0 1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 NaN S 1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38 1 0 PC 17599 71.2833 C85 C 2 3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 NaN S 3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S 4 5 0 3 Allen, Mr. William Henry male 35 0 0 373450 8.05 NaN S
  • 122. Seaborn 회귀분석 그래프 • lmplot() 메소드를 이용하여 회귀분석 판별 • hue 옵션 사용을 통해 기준을 세분화 하여 시각화 가능 df = pd.read_csv('titanic.csv', sep='t') sns.lmplot(x='Age',y='Fare', data=df) #나이별 운임료 회귀분석 sns.lmplot(x='Age',y='Fare', hue='Survived', data=df) #생존여부 기준으로 나이별 운임료 회귀분석
  • 123. Seaborn 회귀분석 그래프 • tips 데이터셋을 이용하여 전체 지불금액(total_bill)과 팁(tip) 상관관계 분석 df = sns.load_dataset('tips') df.head() #생별 기준으로 전체 지불금액과 팀의 상관관계 회귀분석 sns.lmplot(x='total_bill', y='tip', hue='sex', data=df) hue ='smoker'로 했을 경우 total_bill tip sex smoker day time size 0 16.99 1.01 Female No Sun Dinner 2 1 10.34 1.66 Male No Sun Dinner 3 2 21.01 3.5 Male No Sun Dinner 3 3 23.68 3.31 Male No Sun Dinner 2 4 24.59 3.61 Female No Sun Dinner 4
  • 124. Seaborn 히트맵(Heatmap) • 두 개의 카테고리에 해당되는 값의 변화와 분포를 나타낼 때 유리 • DataFrame에서 인덱스와 칼럼이 카테고리 값이 됨 • DataFrame 이용 시 pivot(index, columns, values) 메소드를 이용하여 변조 필요 df = pd.read_csv('titanic.csv', sep='t') #생존자 기준으로 Age, Sex, Fare를 그룹화하여 건수를 추출 tf = df[df.Survived==1].groupby(['Age','Sex','Fare']).count().reset_index() tf = tf[['Age','Sex','Fare','Pclass']] tf = tf.rename(columns={'Pclass':'Count'}) zf = tf.pivot('Age','Fare', 'Count').fillna(0) sns.heatmap(zf) # 연령, 운임에 따른 승객수 현황 Age Sex Fare Count 0 0.83 male 29 1 1 3 female 41.5792 1 2 4 female 16.7 1 3 5 female 27.75 1 4 12 male 11.2417 1
  • 125. Seaborn 히트맵(Heatmap) • df.pivot()의 경우 중복이나 값이 없을 때 아래 에러가 발생 ValueError: Index contains duplicate entries, cannot reshape • pd.pivot_table의 경우는 index의 중복이 있어도 해결 가능 • pd.pivot_table의 경우 aggfunc 옵션이 제공되어 np.sum, np.mean 등 그룹함수 사용 가능 df = pd.read_csv('titanic.csv', sep='t') tf = df.groupby(['Age','Sex','Survived']).count().reset_index().rename(columns={'Pclass':'Count'}) tf = tf[['Age','Sex','Survived','Count']] # 좌측 인덱스가 Age(연령), 상단 칼럼은 Survived(생존여부)로 한 사람수를 나타내는 DataFrame으로 변조 zf = pd.pivot_table(tf,index='Age',columns='Survived',values='Count', aggfunc=np.sum).fillna(0) sns.heatmap(zf) pd.pivot_table(index='Sex', columns='Survived', values='Count', aggfunc=np.sum)
  • 126. Q&A