SlideShare a Scribd company logo
1 of 151
Download to read offline
파이썬
데이터과학
이태영
se2n@naver.com
파이썬을 이용한 데이터 분석,
그리고 머신러닝 실전 입문
레벨-1
자료를 공개하는 이유
# 유명해지고 싶다
# 놀면 뭐하니
# 강의는 취미
# 특허도 취미
# 데이터사이언티스트
# 풀스택개발자
# 비씨카드 # 데이터분석왕 # 이태영
이태영
구글 ‘데이터과학 파이썬‘ 분야 SEO 국내 1위
(경력)
2015 BC FEP 실시간 승인 거래 분석 시스템 설계/개발/구축
2015 BC 집현전 대상 ‘오픈소스를 활용한 빅데이터 플랫폼 구축’
2018 BC R&D Cell 최우수상 ‘AI 기반 서비스 플랫폼 구축’
2020 BC 차세대프로젝트 Scalable FEP/MCI 시스템 구축
(특허/등록건)
2012 고객 단말기의 맥 어드레스 정보를 이용한 결제 방법 및 시스템
2013 고객 단말기의 맥 어드레스 정보를 이용한 결제 방법 및 시스템
2014 카드 상품 추천 방법 및 카드사 서버
2014 사용 업종 예측을 위한 카드 사용 패턴 분석 방법 및 수행 서버
2015 가맹점 개인화 추천 방법 및 가맹점 추천 서버
(논문)
2017 Scalable 네트워크 아키텍처와 In-memory 컴퓨팅에 기반한
실시간 결제 분석 시스템, 고려대.
2018 Abnormal Payment Transaction Detection Scheme
based on Scalable Architecture and Redis Cluster, IEEE.
(자격)
2020 Algorithms Specialization, Stanford University.
2020 Applied Data Science Specialization, University of Michigan.
@관심사 : Scalable Architecture, Machine Learning, Object Detection, Visualization, Data Analysis, Pattern Recognition
#BCCard #IT기획팀 #신기술 #전략기획
무슨 자격으로 강의를 하나요?
파이썬의 장점
• 문과도 잘 할 수 있다.
• 이과도 잘 할 수 있다.
• 60대도 20대보다 잘 할 수 있다.
• 20대도 60대보다 잘 할 수 있다.
• 영업도 IT보다 잘 할 수 있다.
• IT도 영업보다 잘 할 수 있다.
데이터분석 파이썬
• C언어 기반 > 고성능 보장
• 쉬운 사용성
• 풍부한 라이브러리
• 규모의 경제학
• 얕은 수준으로 알고리즘을 알아도 구현 가능
(구글, 스택오버플로우 검색)
독서백편의자현(讀書百遍義自見)
삽질할 용기
강의자료 100번도 말고
딱 3번만 복습
그리고 궁금하면 질문!
모든 데이터셋은 https://github.com/sh2orc/datascience 등록되어 있습니다.
이번 과정을 통해 배울 지식
1. 파이썬 환경
• 개발환경 구축
2. 파이썬 답게 코딩
• 이터러블, 이터레이터, 제네레이터
• 조건문, 리스트 고급 표현식
• 람다(Lambda)
• *args와 **kwargs 이용한 람다
• 파일 입출력, json과 pickle
• 서울시 인구 통계 분석 실습
3. numpy
• 기초 사용법, 배열 붙이기
• 기술통계,
• 랜덤함수, 데이터샘플링, 비교연산
• 최소제곱법 (Least Squares)
• 선형회귀식 (Linear Regression)
4. Pandas
• 기초개념, 데이터프레임
• 컬럼명 변경, 컬럼기준 삭제
• 선택과 변경, 정렬
• 행/열 합계
• 시계열 관리
• 데이터프레임 Merge & Join
• 그룹화 연산
• 피벗 테이블
5. 실전, 데이터분석
• 하루 승인 거래 건수 분석 및 평가
• 전문 거래 로그 분석
• 통계청 행정구역별 인구변화 분석 (2011~2020)
• 코로나19(COVID-19) 감염자 분석 (Kaggle)
1. 파이썬 환경
파이썬을 배우고 싶어요.
그런데 뭘로 코딩하지?
Eclipse Jupyter
무겁지만 강력하다 빠르고 강력하다
• 대화형 컴퓨팅으로 분석 프로그래밍 최적합
• 운영체제의 쉘 파일 시스템과 통합되어있음
• 웹기반의 대화형 노트북 지원으로 수식, 표, 그림 등을 표현 가능
• 가볍고 빠른 병렬컴퓨팅 엔진 이용
• 코딩과 문서화, 테스트까지 한 화면에 OK
Jupyter
Interactive computing python
• python 3.6.10 설치 (윈도우는 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. 파이썬 답게 (pythonic) 코딩
데이터 분석을 위한 코딩 기법
파이썬의 장점
• 문과도 잘 할 수 있다.
• 이과도 잘 할 수 있다.
• 60대도 20대보다 잘 할 수 있다.
• 20대도 60대보다 잘 할 수 있다.
• 영업도 IT보다 잘 할 수 있다.
• IT도 영업보다 잘 할 수 있다.
이것을 알아두면 고급 개발자
• 이터러블
• 이터레이터
• 제네레이터
• One Line 조건문
• 리스트 표현식(List Comprehension)
• 람다함수 (lambda)
• *args, **kwargs 매개변수
• 파일 입출력
• json, pickle
파이썬 답게 코딩하기
이터러블(iterable)
• 파이썬에서는 이터러블(iterable) 객체 개념 존재
• 이터러블은 내부적으로 __iter__라는 메소드(함수)를 가지는 객체
• 이터러블은 3가지 특징
• 반복 처리 가능 (예를 들면 문자열이나 파일)
• for~loop에서 오른쪽에 정의 가능
• iter(이터러블)통해 iterator 객체가 할당
for 임시변수 in iterable(리스트, 튜플, 디셔너리, 함수 등):
구현 코드
for x in [1,2,3,4,5]:
print(x)
for x in range(5):
print(x)
for x in "hello":
print(x)
파이썬 답게 코딩하기
이터레이터(iterator)
• 이터러블(iterable)은 ’순차적으로 접근을 할 수 있는’ 객체들의 통칭
• 이터레이터는(iterator)는 이터러블을 이용하여 변환한 객체
A = iter ('hello’)
next(A) #h
next(A) #e
next(A) #l
next(A) #l
next(A) #o
next(A)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-8-2547a3b71e0f> in <module>
----> 1 next(A)
StopIteration:
파이썬 답게 코딩하기
제네레이터(generator)
• 표현식 혹은 함수를 통해 정의되는 이터레이터(iterator)
• return 키워드가 아닌 yield 키워드가 사용되면 제네레이터
• yield를 이용하면 함수의 끝이 아닌 호출 이후 계속 처리를 의미
def g():
print('one’)
yield 1 #첫번째 next 호출 시 여기까지 처리
print('two’)
yield 2 #두번째 next 호출 시 여기까지 처리
print('three’)
yield 3 #세번째 next 호출 시 여기까지 처리
_ = g()
next(_)
next(_)
next(_)
#반복문 처리 시 활용
def g():
A = [1,2,3,4,5]
for _ in A:
yield _
for _ in g():
print( _ * 2)
파이썬 답게 코딩하기
이터러블(iterable), 이터레이터(iterator), 제네레이터(generator) 관계
제네레이터
(generator)
이터레이터
(iterator)
이터러블
(iterable)
always is
always is iter()
next() lazy produce
next value
{list, set, dict}
등 컨테이너
제네레이터
함수/표현식
for-loop iterable
파이썬 답게 코딩하기
(파이썬 다운) 한줄 조건문
• 파이썬의 조건문은 변수 할당 시점 한줄로 작성이 가능 (if statement in one line)
• 이 경우는 if-else 형식으로 정의 되어야 하며 값표현은 왼쪽, 조건은 오른쪽 표현 특징 (왼손잡이 사고전환)
• 오른쪽에 조건이 정의될 경우 if만 단독적으로 사용 불가하며 else가 꼭 정의되어야 함
b = '참' if (True조건) else '거짓'
b = '참' if (True조건) else '거짓' #거짓 조건일 경우 다시 조건을 넣을 수 있다.
b = '참' if (True조건) else ('거짓>참' if (False-True조건) else '거짓>거짓’)
b = '참' if (True조건) else '거짓>참' if (False-True조건) else '거짓>거짓’ #괄호를 없앨 수 있음
#파이썬의 라인의 끝을  구분자를 작성하고 다음 라인으로 내릴 수 있다.
b = '참' if (True조건) else
'거짓>참' (False-True조건) else
'거짓>거짓'
• else에 추가적인 조건을 계속 넣을 수 있음
파이썬 답게 코딩하기
(파이썬 다운) 한줄 조건문
• 오른쪽에 표현식이 오는 One line 조건문은  백슬래쉬 키를 이용하여 라인을 구분하면 보기 편함
• 이 조건 표현식은 리스트 표현식, 람다문법 등 파이썬의 핵심 표현식으로 알아두는게 좋음
def confirm(x):
return '1입니다' if x == 1 else
'5입니다' if x == 5 else
'1도 5도 아닙니다.’
confirm(1)
1입니다.
confirm(3)
1도 5도 아닙니다.
파이썬 답게 코딩하기
리스트 표현식
• 파이썬에서 리스트는 [ ] 대괄호 안에 쉼표 , 구분자로 분리
A = ['ABC','DEF','HIG’] # A값 ['ABC','DEF','HIG’]
A = [1,2,3,4,5] # A값 [1,2,3,4,5]
A[시작위치:끝위치] # 슬라이싱범위 (시작위치≤ A < 끝위치)
A[시작위치:] # 시작위치부터 끝까지 슬라이싱
A[:끝위치] # 끝위치-1까지 슬라이싱
A = [1,2,3,4,5]
A[:2] # [1,2] 출력
• 리스트는 슬라이싱 가능
A.append(6) # A값 [1,2,3,4,5,6]
del(A[0]) # A값 [2,3,4,5,6]
• 리스트는 추가하고 삭제 가능
파이썬 답게 코딩하기
(파이썬 다운) 리스트 표현식
• 리스트, 튜플, 딕셔너리 등 데이터구조에서 for ~ in 표현식으로 데이터를 가공이 가능
[expression for member in iterable (if conditional)]
[ 임시변수_표현 for 임시변수 in 이터러블 ]
[ 임시변수_표현 for 임시변수 in 이터러블 if 임시변수조건 ] # if 조건만 있을 경우
[ 임시변수_True표현 if 임시변수_True조건 else 임시변수_False표현 for 임시변수 in 이터러블]
• 만약 if-else 조건을 넣을 순간이 온다면 if 조건은 오른쪽이 아닌 임시변수_표현 영역에 구현
[ 임시변수_표현 for 임시변수 in 이터러블 ]
한줄 조건문
파이썬 답게 코딩하기
(파이썬 다운) 리스트 표현식
A = list(range(10)) # [0,1,2,3,4,5,6,7,8,9] 할당
#파이썬에서 _ 문자를 변수명으로 사용 가능함. 쓰고 버리는 의미 없는 임시변수 표현
B = [ _ for _ in A] # [0,1,2,3,4,5,6,7,8,9] 할당
C = [ _ for _ in A if _ > 5] # [6,7,8,9] 할당 = 5보다 큰 값 할당 (필터링 역할)
D = [ _ if _ > 5 else 0 for _ in A ] # [0,0,0,0,0,6,7,8,9] = 5보다 큰 경우 그대로, 작은 경우 0으로 초기화
• 리스트 표현식 예제
[ _ for _ in A if (조건1) and (조건2)]
[ _ for _ in A if (조건1) if (조건2) ]
• 조건을 and 나 or로 묶을 수 있음
• 리스트 표현식에서 if를 여러번 쓰는 것은 and와 같은 처리를 의미
[ _ for _ in A if _ > 5 and _ % 2 == 0] # [6,8] 출력
파이썬 답게 코딩하기
함수(function)
# F(n) = F(n-1) + F(n-2) 단, n>2일 경우
def F(n):
if n <= 2:
return 1
else:
return F(n-1) + F(n-2)
R = [ F(n) for n in range(1,10)]
print(R) #[1, 1, 2, 3, 5, 8, 13, 21, 34]
• 함수는 def를 이용하여 선언
• 피보나치 수열 정의를 이용하여 구현 예제
the sequence starts with F1 = F2 = 1, and the recurrence Fn=Fn−1 +Fn−2 (n > 2)
파이썬 답게 코딩하기
(파이썬 다운) 람다(lambda) 함수
def 함수명(임시변수):
return (임시변수 표현식)
• 파이썬에서 가장 강력한 기능 중 하나
• 익명함수 (Anonymous Function)라고도 부르며, 함수 정의를 한 줄로 생략하는 방식
• 일반적으로 함수가 아래처럼 정의된다면,
함수명 = lambda 임시변수 : (임시변수 표현식)
함수명 = lambda 임시변수 : (True조건 표현식) if 조건 else (Flase조건 표현식)
• lambda 표현식으로 함수명을 변수에 정의하듯 선언
• if-else를 통해 표현이 되며, if 가 정의되면 else 조건도 함께 작성되어야 합니다.
return 되는 값
return 되는 값 return 되는 값
파이썬 답게 코딩하기
(파이썬 다운) 람다(lambda) 함수
• lambda 예제
A = lambda x : x * 2
A(5) #10 값
F = lambda n : F(n-1)+F(n-2) if n > 2 else 1
R = [ F(n) for n in range(1,10)]
print(R) #[1, 1, 2, 3, 5, 8, 13, 21, 34]
• 피보나치 수열 예제
• map 활용 예제
• map은 정의된 함수 F가 있다면, 이터러블(iterable)에 함수 F를 적용한 이터레이터(iterator)로 반환
map(function, iteratble)
A = [1,2,3,4,5]
F = lambda n : F(n-1)+F(n-2) if n > 2 else 1
R = map( F, A ) # R을 출력하면 <map at 0x21d324ab848>
[ _ for _ in R ] #[1, 1, 2, 3, 5]
파이썬 답게 코딩하기
(파이썬 다운) 람다(lambda) 함수
• lambda 예제
A = lambda x : x * 2
B = lambda x : x * 3
C = lambda x : x * 4
D = lambda x : x * 5
L = [A, B, C, D]
for f in L:
print( f(2) )
• 2 값에 대해 L 함수 리스트로 처리할 경우
4
6
8
10
F = lambda n : [ f(n) for f in L ]
F(2) #[4, 6, 8, 10]
• 함수 L에 대한 반복 처리하는 lambda 함수를 다시 정의하면,
파이썬 답게 코딩하기
(파이썬 다운) 람다(lambda) 함수
• 문자열을 Upper-case, Lower-case, Capitalize 시키는 함수
def process(string, code):
func_dict = { 'U' : lambda x : x.upper(),
'L' : lambda x : x.lower(),
'C' : lambda x : x.capitalize()}
F = func_dict[code]
return F(string)
def process(string, code):
return { 'U' : lambda x : x.upper(),
'L' : lambda x : x.lower(),
'C' : lambda x : x.capitalize()
} [code] (string)
• 위 함수를 좀더 줄여쓰면 아래처럼 직접 딕셔너리로 접근 후 함수 호출 가능
process('hello',’U’) # HELLO
process(‘HELLO',’L’) # hello
process(‘hello,’C’) # Hello
파이썬 답게 코딩하기
(파이썬 다운) *args와 **kwargs 이용한 람다
• *args 표현식
함수의 매개변수에 * 문자는 임의의 복수의 매개변수가 오는 것으로 정의
• **kwargs 표현식
함수의 매개변수에 ** 문자는 임의의 key=value 형태의 복수의 매개변수가 오는 것으로 정의
F = lambda *x : ' '.join( x ) # 문자열을 붙여주는 함수
F('파이썬','코딩','쉽네') # '파이썬 코딩 쉽네'
F = lambda **x : [ (v, k) for k, v in x.items()] # key, value를 서로 바꿔서 dictionary 생성
D = ( A = '파이썬', B = '코딩', C='쉽네') # {'파이썬':'A', '코딩':'B', '쉽네':'C'}
D['파이썬'] # 'A' 출력
F = lambda **x : sum(x['data']) if 'type' in x and x['type'] == 'sum' else 0
F(type='sum', data=[1,2,3,4,5])
F(data=[1,2,3,4,5])
F(type='mul', data=[1,2,3,4,5])
• *kwargs를 이용한 변수가 정의되었을 경우 처리 예제
파이썬 답게 코딩하기
파일 입출력
• 파일 처리는 직접 object를 생성하기 보다 with 문을 사용 권고
• with 문에서 선언된 오브젝트는 Context Manager 의해 구문이 끝나는 시점
자동으로 메모리 해제. close() 함수를 호출하지 않아도 됨.
with open(파일명, 'rwa+') as 파일오브젝트변수명:
코드구현
with open('student', 'r') as fr:
print( fr.readline() )
• student 파일 읽기 예제
라인별 이름;국어점수;영어점수;수학점수;과학점수
태서연;54;72;60;78
F = lambda x : x.split(';')[1:]
F('태서연;54;72;60;78')
• 이름(첫번째)를 제외한 숫자 문자열들만 추출
['54' ,'72', '60', '78']
파이썬 답게 코딩하기
(파이썬 다운) 파일 입출력
• 입력 문자열을 숫자로만 추출하기 (list comprehension)
F = lambda x : [ int( _ ) for _ in x.split(';')[1:] ]
F('태서연;54;72;60;78')
[54 ,72, 60, 78]
F = lambda x : sum([ int( _ ) for _ in x.split(';')[1:] ])
F('태서연;54;72;60;78')
• 입력 문자열을 합계
264
F = lambda x : ( x.split(';')[0] , sum([ int( _ ) for _ in x.split(';')[1:] ]) )
name, total = F('태서연;54;72;60;78')
print( name, total )
• 이름, 과목별 점수 합계 리턴
태서연 264
파이썬 답게 코딩하기
(파이썬 다운) 파일 입출력
• 입력 문자열을 미리 split 하여서 리스트로 넘긴다고 가정
F = lambda L : [ int( _ ) for _ in L[1:] ]
F('태서연;54;72;60;78'.split(';'))
[54 ,72, 60, 78]
F = lambda L : ( L[0] , sum([ int( _ ) for _ in L[1:] ]) )
name, total = F('태서연;54;72;60;78'.split(';'))
print( name, total )
• 이름, 점수 합계를 리턴하는 방법
태서연 264
F = lambda L, T : ( L[0] , sum([ int( _ ) for _ in L[1:] ]) ) if T == 'sum' else
( L[0] , sum([ int( _ ) for _ in L[1:] ]) / len(L[1:]) ) if T == 'avg' else
( L[0] , None )
• 타입별 (이름, 합계), (이름, 평균)을 나타내는 함수
파이썬 답게 코딩하기
(파이썬 다운) 파일 입출력
• 파일을 읽어서 이름;합계;평균을 내는 student_result 파일로 저장
with open('student','r') as fr, open('student_result','w') as fw:
for line in fr:
name, total_sum = F(line.split(';'), 'sum')
name, total_avg = F(line.split(';'), 'avg')
# 문자열 앞에 f를 붙이면 문자열 내부에 { }를 이용하여 변수를 바인딩 할 수 있음. f-string
result = f"{name};{total_sum};{total_avg}n"
fw.write(result)
• 저장된 내용 확인
with open('student_result') as fr:
print(fr.readline())
print(fr.readline())
print(fr.readline())
파이썬 답게 코딩하기
(파이썬 다운) 데이터를 json 파일/텍스트로 변환
• json.dumps( dict ) - 딕셔너리를 json 문자열로 변환 가능
• json.dump( dict, file object ) - 딕셔너리를 json 문자열 형태로 file object에 저장
import json
person_dict = {} # 딕셔너리
with open('student','r') as fr, open('student_json', 'w') as fw:
for line in fr:
data = line.strip().split(';') #불필요 공백 제거 후 ; 문자로 문자열 분리
name = data[0] #이름
# kor, eng, mat, sci = int(data[1]), int(data[2]), int(data[3]), int(data[4])
kor, eng, mat, sci = ( int( _ ) for _ in data[1:] )
person_dict[name] = { '국어' : kor, '영어' : eng,
'수학' : mat, '과학' : sci }
json.dump( person_dict, fw) # 딕셔너리를 JSON으로 변환하여 파일로 저장
json_data = json.dumps( person_dict ) # 딕셔너리를 JSON 문자열로 변환
print(json_data) # JSON 문자열 확인
파이썬 답게 코딩하기
(파이썬 다운) 파이썬 오브젝트를 json 텍스트로 변환
• json dump(s)에 ensure_ascii = False를 지정해야 한글들이 유니코드로 변환되는 것을 방지
• json dump(s)에 indent = 숫자를 지정하면 숫자만큼 깔끔하게 인덴트 추가
import json
person_dict = {} # 딕셔너리
with open('student','r') as fr
for line in fr:
data = line.strip().split(';') #불필요 공백 제거 후 ; 문자로 문자열 분리
name = data[0] #이름
kor, eng, mat, sci = ( int( _ ) for _ in data[1:] )
person_dict[name] = { '국어' : kor, '영어' : eng,
'수학' : mat, '과학' : sci }
json_data = json.dumps( person_dict, ensure_ascii=False, indent=4 ) # 한글 보존, indent 추가
print(json_data)
파이썬 답게 코딩하기
(파이썬 다운) json 텍스트를 파이썬 오브젝트로 변환
import json
with open('student_json', 'r' , encoding='UTF-8-sig') as fr
json_data = json.load(fr)
print( json_data['태서연'] ) # {'국어': 54, '영어': 72, '수학': 60, '과학': 78}
with open('student_json', 'r' , encoding='UTF-8-sig') as fr
json_text = ''.join(fr.readlines())
json_data = json.loads(json_text)
print( json_data['태서연'] ) # {'국어': 54, '영어': 72, '수학': 60, '과학': 78}
• json.loads( 텍스트 ) - JSON 형태의 텍스트를 파이썬 오브젝트로 변환
• json.load( file object ) - 파일에 저장된 JSON 텍스트를 파이썬 오브젝트로 변환
파이썬 답게 코딩하기
(파이썬 다운) pickle - 데이터 직렬화 저장/로딩
import json
import pickle
with open('student_json', 'r' , encoding='UTF-8-sig') as fr:
json_data = json.load(fr)
with open('student_pickle', 'wb') as fw:
pickle.dump(json_data, fw)
with open('student_pickle', 'rb') as fr:
pickle_data = pickle.load(fr)
print( pickle_data['태서연'] ) # {'국어': 54, '영어': 72, '수학': 60, '과학': 78}
• 파이썬에서는 pickle 이라는 패키지를 통해 데이터를 직렬화하여 바이너리 형태로 저장
• 사용법은 json 패키지와 동일하게 dump(s), load(s) 함수를 통해 저장/로딩
파이썬 답게 코딩하기
서울시 인구 통계 분석 (실습)
• seoul_people_report (CSV) 파일을 기반으로 구명을 key 값을 가지는 딕셔너리로 변경
• 구별 '외국인 비율', '65세이상고령자 비율'을 계산 후 각각 key(외국인비율, 고령자비율)에 저장
자치구,전체,남자,여자,외국인,65세이상고령자
합계,10013781,4874995,5138786,280126,1518239
종로구,161984,78271,83713,10767,28073
중구,136469,66769,69700,10294,23794
용산구,246165,119961,126204,16586,39439
성동구,307193,149891,157302,8151,44728
광진구,365990,176226,189764,15573,48989
동대문구,362793,178202,184591,16637,60367
중랑구,400678,198122,202556,5059,66764
성북구,454532,218561,235971,12038,72172
강북구,316750,154141,162609,3765,61660
도봉구,333495,162774,170721,2257,60023
노원구,535495,258696,276799,4458,82682
은평구,482509,231953,250556,4490,82245
서대문구,325875,154502,171373,13233,53038
마포구,386086,181204,204882,11516,53283
양천구,460532,226109,234423,4193,62761
강서구,595703,288134,307569,6401,85992
구로구,438308,218970,219338,32471,67432
금천구,251370,128643,122727,18787,38508
영등포구,404766,202617,202149,32863,59373
동작구,407802,196943,210859,12788,63378
관악구,516662,258982,257680,17288,76664
서초구,434801,207877,226924,4233,58332
강남구,549898,263163,286735,5094,72602
송파구,680883,329058,351825,6788,89539
강동구,457042,225226,231816,4396,66401
seoul_people_report
with open('seoul_people_report', 'r' , encoding='UTF-8-sig') as fr:
raw_list = [ _.strip() for _ in fr.readlines() ] #라인별로 분할
raw_split = [_.split(',') for _ in raw_list ] #각 라인을 , 로 분할
district_dict = {}
for data in raw_split[1:]: #상단 헤더를 제외
ds_name = data[0]
_1, _2, _3, _4, _5 = ( int(_) for _ in arr[1:])
district_dict[ ds_name ] = {'전체': _1, '남자': _2, '여자': _3,
'외국인': _4, '고령자': _5}
for k, v in district_dict.items():
# 실습 구현
# district_dict['종로구']['외국인비율']
# district_dict['종로구']['고령자비율']
#json 형태로 seoul_people_json 으로 저장
코드 실습
파이썬 답게 코딩하기
서울시 인구 통계 분석 (실습)
• lambda 식을 이용하여 딕셔너리 키 값, 기준값을 받아서 조건을 충족하면 그대로, 미충족 시 None
• 고령자 비율 15%가 넘고, 외국인 비율이 5%를 넘는 구의 인력현황 출력 및 저장
자치구,전체,남자,여자,외국인,65세이상고령자
합계,10013781,4874995,5138786,280126,1518239
종로구,161984,78271,83713,10767,28073
중구,136469,66769,69700,10294,23794
용산구,246165,119961,126204,16586,39439
성동구,307193,149891,157302,8151,44728
광진구,365990,176226,189764,15573,48989
동대문구,362793,178202,184591,16637,60367
중랑구,400678,198122,202556,5059,66764
성북구,454532,218561,235971,12038,72172
강북구,316750,154141,162609,3765,61660
도봉구,333495,162774,170721,2257,60023
노원구,535495,258696,276799,4458,82682
은평구,482509,231953,250556,4490,82245
서대문구,325875,154502,171373,13233,53038
마포구,386086,181204,204882,11516,53283
양천구,460532,226109,234423,4193,62761
강서구,595703,288134,307569,6401,85992
구로구,438308,218970,219338,32471,67432
금천구,251370,128643,122727,18787,38508
영등포구,404766,202617,202149,32863,59373
동작구,407802,196943,210859,12788,63378
관악구,516662,258982,257680,17288,76664
서초구,434801,207877,226924,4233,58332
강남구,549898,263163,286735,5094,72602
송파구,680883,329058,351825,6788,89539
강동구,457042,225226,231816,4396,66401
seoul_people_report
#특정 기준 값이 기준치를 넘으면 그대로 출력, 미달이면 None
F = lambda dataset, k, std :
dataset[k] if dataset[k] > std else None
for key, val in district_dict.items():
R = F(val, '고령자비율', 15)
if R is not None:
print(k, R)
district_list = []
#실습코딩
#고령자 비율 15% 넘고, 외국인 비율 5%를 넘는 구의 인력현황
#district_list에 위 조건에 맞는 딕셔너리들을 저장
#district_list는 json을 이용하여 seoul_people_output 파일로 저장
코드 실습
3. 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(x, 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)
• polyfit과 poly1d를 이용한 선형회귀
• np.polyfit(x array, y array, degree) : 주어진 측정 값들로 다항식의 계수를 구함
• x array, y array값을 입력, degree는 다항식의 차수
• x array는 좌표에서 X축을 구성하는 데이터셋, y array는 좌표에서 Y축을 구성하는 데이터셋
• 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 함수로 연산
Numpy
선형회귀(Linear Regression)
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(x, 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에서 데이터셋 다운로드 가능
#컬럼 헤더가 없는 파일의 경우는 name= 옵션을 통해 지정해줄 수 있다.
df = pd.read_csv('trns_msg_info', names=['MSG_CODE', 'MSG_NAME'], dtype=str)
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 3가지 방법
• pd.DataFrame.columns = [ '칼럼1', '칼럼2', … , ] 이용
• pd.DataFrame.rename( { 'OLD칼럼명' : 'NEW칼럼명', …, }, axis=1) 이용
• pd.DataFrame.rename(columns={ 'OLD칼럼명' : 'NEW칼럼명', …, }) 이용
df = pd.read_csv('trns_msg_info', 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승인취소 요청
Pandas
apply 함수 - 컬럼(Series) 데이터 변경
• 특정 컬럼의 값들을 함수를 매핑하여 고속으로 값들을 변조나 생성 가능 (강력한 기능 중 하나)
• df['컬럼명'].apply(함수) 방식을 통해 처리하며 일반적으로 함수에는 lambda 식으로 표현
• .applymap() 존재하며 이것은 대상 데이터프레임의 전체 요소마다 함수를 적용하는 것이다.
#MSG_NAME의 값들 중 빈칸들을 모두 제거하고자 할 때
df['MSG_NAME'] = df.MSG_NAME.apply( lambda x: x.replace(' ','') )
# MSG_NAME이 IC로 시작하는지 여부를 컬럼명 'IS_IC'로 생성
df['IS_IC'] = df.MSG_NAME.apply( lambda x: True if x[:2] == 'IC' else False )
CODE MSG_NAME
0 0100 MS승인요청
1 0110 MS승인응답
2 0300 IC승인요청
3 0310 IC승인응답
4 0420 MS승인취소요청
CODE MSG_NAME IS_IC
0 0100 MS승인요청 False
1 0110 MS승인응답 False
2 0300 IC승인요청 True
3 0310 IC승인응답 True
4 0420 MS승인취소요청 False
df = pd.read_csv('trns_msg_info', 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('trns_msg_info', 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('trns_msg_info', 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('trns_msg_info', 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
Pandas
pivot 테이블
• 데이터프레임을 특정 기준으로 재구성을 하는 방법
• .pivot() 메소드, .pivot_table() 메소드가 있으나 pivot_table를 많이 씀
• .pivot_table(index=['칼럼명',…], columns=['컬럼명',...], aggfunc=[함수], fill_value=...)
• index : 피벗 테이블 생성 시 인덱스 영역으로 그룹핑할 대상
• colums : 피벗 테이블 생성 시 컬럼 영역으로 그룹핑할 대상
• aggfunc : 그룹핑한 이후 처리되는 함수, 기본적으로 np.means(평균)가 적용
df = pd.read_csv('student_exam_result')
df.head()
df.columns
Index(['이름', '과목', '점수', '재시험회수', '합격여부', '건수'], dtype='object')
이름 과목 점수 재시험회수 합격여부
0 이혜원 과학 90 3 Passed
1 김현서 과학 75 1 Passed
2 박지유 국어 51 2 Failed
3 태시아 국어 51 2 Failed
4 김수아 수학 32 2 Failed
Pandas
pivot 테이블
# aggfunc는 default로 np.means 지정 숫자인 '재시험회수', '점수'의 평균이 출력됨
df.pivot_table(index=['합격여부'])
재시험회수 점수
합격여부
Failed 2.079439 47.892523
Passed 1.891192 84.284974
# index로 '과목'과 '합격여부'를 지정하면 멀티 Index로 지정됨
df.pivot_table(index=['과목', '합격여부'])
재시험회수 점수
과목 합격여부
과학 Failed 2.156250 65.281250
Passed 2.014706 85.911765
국어 Failed 2.261905 59.500000
Passed 1.793103 84.379310
수학 Failed 2.000000 42.491525
Passed 1.756098 83.463415
영어 Failed 2.012987 38.103896
Passed 2.043478 80.739130
철학 Failed 2.000000 55.000000
Passed 1.666667 84.000000
Pandas
pivot 테이블
# columns에 지정된 컬럼은 카테고리화 되는데, 이 때 수치 값을 가지는 컬럼의 하위 그룹핑이 됨
# 재시험회수는 1,2,3 값으로 분포되어 있으며, columns에 지정되어 '점수' 하위 컬럼으로 재매핑
df.pivot_table(index=['과목', '합격여부'], columns=['재시험회수'])
점수
재시험회수 1 2 3
과목 합격여부
과학 Failed 64.375000 66.181818 65.076923
Passed 86.120000 86.529412 85.307692
국어 Failed 56.625000 60.400000 60.000000
Passed 84.666667 85.000000 82.666667
수학 Failed 42.434783 44.461538 41.434783
Passed 85.578947 81.307692 82.111111
영어 Failed 38.500000 37.214286 38.720000
Passed 82.750000 80.214286 80.600000
철학 Failed 54.000000 63.500000 39.000000
Passed 84.000000 84.000000 NaN
df['재시험회수'].unique()
array([3, 1, 2], dtype=int64)
Pandas
pivot 테이블
#df.pivot_table(index=['과목', '합격여부'], columns=['재시험회수'])
df.pivot_table(index=['과목'], columns=['합격여부','재시험회수']) # 합격여부를 컬럼으로 옮겨서 표현
점수
합격여부 Failed Passed
재시험회수 1 2 3 1 2 3
과목
과학 64.375000 66.181818 65.076923 86.120000 86.529412 85.307692
국어 56.625000 60.400000 60.000000 84.666667 85.000000 82.666667
수학 42.434783 44.461538 41.434783 85.578947 81.307692 82.111111
영어 38.500000 37.214286 38.720000 82.750000 80.214286 80.600000
철학 54.000000 63.500000 39.000000 84.000000 84.000000 NaN
• 멀티 인덱스가 가능한 것처럼 멀티 컬럼도 가능
Pandas
pivot 테이블
• 각 컬럼들의 수치 연산은 axis=1 옵션을 통해 처리 가능 (미입력시 Row 기준 합계)
tf = df.pivot_table(index=['과목'], columns=['합격여부','재시험회수'], aggfunc=len)[['점수']]
tf['합계'] = tf['점수'].sum(axis=1) #새로운 컬럼 '합계'로 결과 저장
점수 합계
합격여부 Failed Passed
재시험회수 1 2 3 1 2 3
과목
과학 8.0 11.0 13.0 25.0 17.0 26.0 100.0
국어 8.0 15.0 19.0 24.0 22.0 12.0 100.0
수학 23.0 13.0 23.0 19.0 13.0 9.0 100.0
영어 24.0 28.0 25.0 4.0 14.0 5.0 100.0
철학 1.0 2.0 1.0 1.0 2.0 NaN 7.0
• stack - 상단 헤더 컬럼들을 index 기준으로 각각 재그룹화 (기존 인덱스의 하위 레벨로 그룹핑)
• unstack - 멀티 인덱스를 컬럼 기준으로 재그룹화 시키는 방법 (기존 헤더의 하위 레벨로 그룹핑)
_f = pd.DataFrame([[1,'A'], [2,'B']], columns=['C1','C2'], index=['I1','I2'])
C1 C2
1 A
2 B
I1
I2
_f.stack()
I1 C1 1
C2 A
I2 C1 2
C2 B
dtype: object
C1
C2
1
A
2
B
I1
I2 C1
C2
인덱스
인덱스
values in Series
DataFrame
Pandas
stack과 unstack
• stack - 상단 헤더 컬럼들을 index 기준으로 각각 재그룹화 (기존 인덱스의 하위 레벨로 그룹핑)
• unstack - 멀티 인덱스를 컬럼 기준으로 재그룹화 시키는 방법 (기존 헤더의 하위 레벨로 그룹핑)
_f.stack()
I1 C1 1
C2 A
I2 C1 2
C2 B
dtype: object
C1
C2
1
A
2
B
I1
I2 C1
C2
인덱스
C1 C2
1 A
2 B
I1
I2
인덱스
_f.stack().unstack()
Pandas
stack과 unstack
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['SEC_GAP'] = tf['TIME_GAP'].dt.seconds
tf['COUNT'] = 1
# 처리시간별 현황
tf.groupby('SEC_GAP').sum() # 처리시간 그룹 후 해당 그룹별 합계 (숫자로 지정된 항목인 COUNT만 수행)
# 차트 출력
df = tf.groupby('SEC_GAP')
df.plot(kind='bar')
COUNT
SEC_GAP
0 91
1 96
2 112
3 96
4 99
5 106
6 99
7 94
8 104
9 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)) # 차트 출력
(3) 행정구역별 인구변화 분석
통계청(kosis.kr) 데이터셋 이용
• 통계청 행정구역별 인구 데이터 http://kosis.kr/statHtml/statHtml.do?orgId=101&tblId=DT_1B040A3
• 데이터를 다운 받을 때 '셀병합' 체크를 없앤 뒤 다운로드
• 데이터를 열어보면 아래의 형식이며 파일명은 '행정구역_시군구_별__성별_인구수_2011_2020' 변경
행정구역(시군구)별 2011. 01 2011. 01 2011. 01 2011. 02 2011. 02 2011. 02 2011. 03 2011. 03
행정구역(시군구)별 총인구수 (명) 남자인구수 (명) 여자인구수 (명) 총인구수 (명) 남자인구수 (명) 여자인구수 (명) 총인구수 (명) 남자인구수 (명)
전국 50,534,731 25,318,961 25,215,770 50,555,262 25,328,299 25,226,963 50,575,130 25,337,290
서울특별시 10,312,835 5,110,837 5,201,998 10,314,245 5,110,818 5,203,427 10,307,783 5,107,011
부산광역시 3,566,560 1,772,383 1,794,177 3,566,480 1,772,175 1,794,305 3,564,873 1,770,952
대구광역시 2,512,071 1,255,238 1,256,833 2,512,321 1,255,200 1,257,121 2,511,231 1,254,360
인천광역시 2,761,122 1,391,674 1,369,448 2,765,025 1,393,626 1,371,399 2,768,648 1,395,330
광주광역시 1,456,308 722,450 733,858 1,458,195 723,413 734,782 1,458,326 723,279
대전광역시 1,504,617 754,111 750,506 1,506,136 754,883 751,253 1,506,995 755,385
울산광역시 1,127,337 579,518 547,819 1,127,647 579,732 547,915 1,128,324 580,047
세종특별자치시 - - - - - - - -
경기도 11,801,232 5,949,477 5,851,755 11,815,120 5,956,364 5,858,756 11,829,316 5,963,948
강원도 1,528,790 769,339 759,451 1,527,843 768,790 759,053 1,529,915 769,993
충청북도 1,550,474 781,774 768,700 1,551,621 782,255 769,366 1,552,707 782,832
충청남도 2,076,239 1,049,848 1,026,391 2,077,703 1,050,677 1,027,026 2,081,390 1,052,537
전라북도 1,868,745 931,489 937,256 1,868,363 931,323 937,040 1,868,476 931,437
전라남도 1,916,912 957,989 958,923 1,914,191 956,670 957,521 1,914,176 956,526
경상북도 2,688,586 1,350,687 1,337,899 2,687,178 1,349,953 1,337,225 2,687,521 1,350,106
경상남도 3,291,435 1,656,488 1,634,947 3,291,281 1,656,537 1,634,744 3,293,002 1,657,395
제주특별자치도 571,468 285,659 285,809 571,913 285,883 286,030 572,447 286,152
(3) 행정구역별 인구변화 분석
통계청(kosis.kr) 데이터셋 이용
• jupyter notebook을 위한 설정
출력 차트 사이즈를 조정을 위해 figure.figsize 설정
폰트는 맑은고딕 font.sans-serif, font.weight 설정
%matplotlib inline # 차트 웹에서 출력하는 jupyter notebook 매직키워드
import pandas as pd
from matplotlib import rcParams
rcParams['font.sans-serif'] = 'Malgun Gothic'
rcParams['font.weight']='regular'
rcParams['figure.figsize'] = 15,10
(3) 행정구역별 인구변화 분석
Level 2 멀티컬럼 클린징 방법
#인코딩은 UTF-8, 상단 2개 로우를 헤더로, 첫번째 컬럼을 인덱스로 지정
df = pd.read_csv('행정구역_시군구_별__성별_인구수_2011_2020', header=[0,1], index_col=0)
df.head()
#멀티 컬럼들에 공백과 '(명)'문자를 제거가 필요
#컬럼을 출력함
for _ in df.columns:
print(_)
('2011. 01', '총인구수 (명)')
('2011. 01', '남자인구수 (명)')
('2011. 01', '여자인구수 (명)')
('2011. 02', '총인구수 (명)')
('2011. 02', '남자인구수 (명)')
('2011. 02', '여자인구수 (명)')
('2011. 03', '총인구수 (명)')
행정구역(시군구)별 2011. 01 ... 2020. 04 2020. 05
행정구역(시군구)별
총인구수
(명)
남자인구수
(명)
여자인구수
(명)
...
총인구수
(명)
남자인구수
(명)
여자인구수
(명)
총인구수
(명)
남자인구수
(명)
여자인구수
(명)
전국 50,534,731 25,318,961 25,215,770 ... 51,842,524 25,857,509 25,985,015 51,841,371 25,856,030 25,985,341
서울특별시 10,312,835 5,110,837 5,201,998 ... 9,726,787 4,737,843 4,988,944 9,724,496 4,735,431 4,989,065
(3) 행정구역별 인구변화 분석
Level 2 멀티컬럼 클린징 방법
#컬럼들에 존재하는 문자들은 모두 클린징하여 봄
for x in df.columns:
print( [_.replace(' ','').replace('(명)','') for _ in x ] )
# df.rename( columns={ '옛이름':'신이름', ... } )에 사용될 딕셔너리 생성
colset = {}
for x in df.columns:
y = [ _.replace(' ','').replace('(명)','') for _ in x ]
colset[x] = tuple(y)
colset
['2011.01', '총인구수']
['2011.01', '남자인구수']
['2011.01', '여자인구수']
['2011.02', '총인구수']
['2011.02', '남자인구수']
['2011.02', '여자인구수']
{('2011. 01', '총인구수 (명)'): ('2011.01', '총인구수'),
('2011. 01', '남자인구수 (명)'): ('2011.01', '남자인구수'),
('2011. 01', '여자인구수 (명)'): ('2011.01', '여자인구수'),
('2011. 02', '총인구수 (명)'): ('2011.02', '총인구수'),
('2011. 02', '남자인구수 (명)'): ('2011.02', '남자인구수'),
('2011. 02', '여자인구수 (명)'): ('2011.02', '여자인구수'), ..... }
(3) 행정구역별 인구변화 분석
Level 2 멀티컬럼 클린징 방법
#컬럼명 변경
df = df.rename(columns=colset)
df.head()
#데이터프레임의 Level 2의 멀티컬럼을 Level 1로 변경 (튜플 지정)
df.columns=df.columns.values
(2011. 01,
총인구수
(명))
(2011. 01,
남자인구
수 (명))
(2011. 01,
여자인구
수 (명))
(2011. 02,
총인구수
(명))
(2011. 02,
남자인구
수 (명))
...
(2020. 04,
여자인구
수 (명))
(2020. 05,
총인구수
(명))
(2020. 05,
남자인구
수 (명))
(2020. 05,
여자인구
수 (명))
전국 50,534,731 25,318,961 25,215,770 50,555,262 25,328,299 25,237,840 25,857,509 25,985,015 51,841,371 25,856,030
서울특별시 10,312,835 5,110,837 5,201,998 10,314,245 5,110,818 5,200,772 4,737,843 4,988,944 9,724,496 4,735,431
(2011.01,
총인구수)
(2011.01,
남자인구수)
(2011.01,
여자인구수)
(2011.02,
총인구수)
(2011.02,
남자인구수)
...
(2020.04,
여자인구수)
(2020.05,
총인구수)
(2020.05,
남자인구수)
전국 50,534,731 25,318,961 25,215,770 50,555,262 25,328,299 ... 25,985,015 51,841,371 25,856,030
서울특별시 10,312,835 5,110,837 5,201,998 10,314,245 5,110,818 ... 4,988,944 9,724,496 4,735,431
(3) 행정구역별 인구변화 분석
Level 2 멀티컬럼 클린징 방법
#튜플 기준으로 멀티 헤더의 인덱스로 변경함
df.columns=pd.MultiIndex.from_tuples(df.columns)
2011.01 2011.02 ... 2020.04 2020.05
총인구수
남자인구
수
여자인구
수
총인구수
남자인구
수
여자인구
수
... 총인구수
남자인구
수
여자인구
수
총인구수
남자인구
수
여자인구
수
전국
50,534,7
31
25,318,9
61
25,215,7
70
50,555,2
62
25,328,2
99
25,226,9
63
...
51,842,5
24
25,857,5
09
25,985,0
15
51,841,3
71
25,856,0
30
25,985,3
41
서울특별시
10,312,8
35
5,110,83
7
5,201,99
8
10,314,2
45
5,110,81
8
5,203,42
7
...
9,726,78
7
4,737,84
3
4,988,94
4
9,724,49
6
4,735,43
1
4,989,06
5
(3) 행정구역별 인구변화 분석
데이터프레임 .T : Trnaspose Index and Columns
tf = df.T
2011.01 2011.02 ... 2020.04 2020.05
총인구
수
남자인구수 여자인구수 총인구수 남자인구수 여자인구수 ... 총인구수 남자인구수 여자인구수 총인구수 남자인구수 여자인구수
전국
50,534,
731
25,318,961 25,215,770 50,555,262 25,328,299 25,226,963 ... 51,842,524 25,857,509 25,985,015 51,841,371 25,856,030 25,985,341
서울특별시
10,312,
835
5,110,837 5,201,998 10,314,245 5,110,818 5,203,427 ... 9,726,787 4,737,843 4,988,944 9,724,496 4,735,431 4,989,065
• 시계열 형식으로 변경해야 데이터의 변화를 분석하기 쉬움
• 데이터프레임에는 .T를 통해 인덱스와 컬럼의 위치를 변경할 수 있음
전국 서울특별시 부산광역시 대구광역시 인천광역시 광주광역시 대전광역시 울산광역시
세종특별자
치시
...
2011.01 총인구수 50,534,731 10,312,835 3,566,560 2,512,071 2,761,122 1,456,308 1,504,617 1,127,337 - ...
남자인구수 25,318,961 5,110,837 1,772,383 1,255,238 1,391,674 722,450 754,111 579,518 - ...
여자인구
수
25,215,77
0
5,201,998 1,794,177 1,256,833 1,369,448 733,858 750,506 547,819 - 5,851,755
... ... ... ... ... ... ... ... ... ... ... ...
df
df.T
(3) 행정구역별 인구변화 분석
데이터프레임 .unstack : 시계열만 인덱스로 남기고 컬럼을 그룹핑
전국 서울특별시 부산광역시 대구광역시 인천광역시 광주광역시 ...
2011.01
총인구수 50534731 10312835 3566560 2512071 2761122 1456308 ...
남자인구수 25318961 5110837 1772383 1255238 1391674 722450 ...
여자인구수 25215770 5201998 1794177 1256833 1369448 733858 ...
2011.02
총인구수 50555262 10314245 3566480 2512321 2765025 1458195 ...
남자인구수 25328299 5110818 1772175 1255200 1393626 723413 ...
여자인구수 ... ... ... ... ... ... ...
# unstack()을 통해 멀티 인덱스 한 개를 컬럼 차원으로 재그룹핑
tf = tf.unstack()
전국 서울특별시 부산광역시
총인구수 남자인구수 여자인구수 총인구수 남자인구수 여자인구수 총인구수 남자인구수 여자인구수 ...
2011.01 50534731 25318961 25215770 10312835 5110837 5201998 3566560 1772383 1794177 ...
2011.02 50555262 25328299 25226963 10314245 5110818 5203427 3566480 1772175 1794305 ...
2011.03 50575130 25337290 25237840 10307783 5107011 5200772 3564873 1770952 1793921 ...
2011.04 50594424 25346019 25248405 10301829 5103919 5197910 3563042 1769903 1793139 ...
(3) 행정구역별 인구변화 분석
데이터 시각화
# 인덱스가 X축이 되며, 나머지 값들이 Y축이 되어 출력됨
tf.plot()
(3) 행정구역별 인구변화 분석
데이터 시각화
# 서울특별시로 한정하여 출력
tf['서울특별시'].plot()
(3) 행정구역별 인구변화 분석
데이터 시각화
# 세종특별자치시로 한정하여 출력
tf['세종특별자치시'].plot()
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)

More Related Content

What's hot

TenforFlow Internals
TenforFlow InternalsTenforFlow Internals
TenforFlow InternalsKiho Hong
 
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영Tae Young Lee
 
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)Kyoungchan Lee
 
Python vs Java @ PyCon Korea 2017
Python vs Java @ PyCon Korea 2017Python vs Java @ PyCon Korea 2017
Python vs Java @ PyCon Korea 2017Insuk (Chris) Cho
 
Let's Go (golang)
Let's Go (golang)Let's Go (golang)
Let's Go (golang)상욱 송
 
PyCon 12월 세미나 - 실전 파이썬 프로그래밍 책 홍보
PyCon 12월 세미나 - 실전 파이썬 프로그래밍 책 홍보PyCon 12월 세미나 - 실전 파이썬 프로그래밍 책 홍보
PyCon 12월 세미나 - 실전 파이썬 프로그래밍 책 홍보Young Hoo Kim
 
Python 생태계의 이해
Python 생태계의 이해Python 생태계의 이해
Python 생태계의 이해용 최
 
Writing Fast Code (KR)
Writing Fast Code (KR)Writing Fast Code (KR)
Writing Fast Code (KR)Younggun Kim
 
빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)SeongHyun Ahn
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기지수 윤
 
모두의 JIT 컴파일러
모두의 JIT 컴파일러모두의 JIT 컴파일러
모두의 JIT 컴파일러우경 성
 
니름: 쉬운 SOA 단위 테스트
니름: 쉬운 SOA 단위 테스트니름: 쉬운 SOA 단위 테스트
니름: 쉬운 SOA 단위 테스트효준 강
 
Python을 활용한 챗봇 서비스 개발 2일차
Python을 활용한 챗봇 서비스 개발 2일차Python을 활용한 챗봇 서비스 개발 2일차
Python을 활용한 챗봇 서비스 개발 2일차Taekyung Han
 
파이썬 라이브러리로 쉽게 시작하는 데이터 분석
파이썬 라이브러리로 쉽게 시작하는 데이터 분석파이썬 라이브러리로 쉽게 시작하는 데이터 분석
파이썬 라이브러리로 쉽게 시작하는 데이터 분석Heekyung Yoon
 
20150212 c++11 features used in crow
20150212 c++11 features used in crow20150212 c++11 features used in crow
20150212 c++11 features used in crowJaeseung Ha
 
1.Introduction to Python and TensorFlow
1.Introduction to Python and TensorFlow1.Introduction to Python and TensorFlow
1.Introduction to Python and TensorFlowHaesun Park
 
알고리즘 시각화 라이브러리 ipytracer 개발기
알고리즘 시각화 라이브러리 ipytracer 개발기알고리즘 시각화 라이브러리 ipytracer 개발기
알고리즘 시각화 라이브러리 ipytracer 개발기Han Lee
 

What's hot (20)

TenforFlow Internals
TenforFlow InternalsTenforFlow Internals
TenforFlow Internals
 
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
 
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
GopherCon Korea 2015 - Python 개발자를 위한 Go (이경찬)
 
Python vs Java @ PyCon Korea 2017
Python vs Java @ PyCon Korea 2017Python vs Java @ PyCon Korea 2017
Python vs Java @ PyCon Korea 2017
 
Let's Go (golang)
Let's Go (golang)Let's Go (golang)
Let's Go (golang)
 
PyCon 12월 세미나 - 실전 파이썬 프로그래밍 책 홍보
PyCon 12월 세미나 - 실전 파이썬 프로그래밍 책 홍보PyCon 12월 세미나 - 실전 파이썬 프로그래밍 책 홍보
PyCon 12월 세미나 - 실전 파이썬 프로그래밍 책 홍보
 
Python 생태계의 이해
Python 생태계의 이해Python 생태계의 이해
Python 생태계의 이해
 
Writing Fast Code (KR)
Writing Fast Code (KR)Writing Fast Code (KR)
Writing Fast Code (KR)
 
빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
 
파이썬으로 익히는 딥러닝
파이썬으로 익히는 딥러닝파이썬으로 익히는 딥러닝
파이썬으로 익히는 딥러닝
 
모두의 JIT 컴파일러
모두의 JIT 컴파일러모두의 JIT 컴파일러
모두의 JIT 컴파일러
 
Go
GoGo
Go
 
Boost
BoostBoost
Boost
 
니름: 쉬운 SOA 단위 테스트
니름: 쉬운 SOA 단위 테스트니름: 쉬운 SOA 단위 테스트
니름: 쉬운 SOA 단위 테스트
 
Python을 활용한 챗봇 서비스 개발 2일차
Python을 활용한 챗봇 서비스 개발 2일차Python을 활용한 챗봇 서비스 개발 2일차
Python을 활용한 챗봇 서비스 개발 2일차
 
파이썬 라이브러리로 쉽게 시작하는 데이터 분석
파이썬 라이브러리로 쉽게 시작하는 데이터 분석파이썬 라이브러리로 쉽게 시작하는 데이터 분석
파이썬 라이브러리로 쉽게 시작하는 데이터 분석
 
20150212 c++11 features used in crow
20150212 c++11 features used in crow20150212 c++11 features used in crow
20150212 c++11 features used in crow
 
1.Introduction to Python and TensorFlow
1.Introduction to Python and TensorFlow1.Introduction to Python and TensorFlow
1.Introduction to Python and TensorFlow
 
알고리즘 시각화 라이브러리 ipytracer 개발기
알고리즘 시각화 라이브러리 ipytracer 개발기알고리즘 시각화 라이브러리 ipytracer 개발기
알고리즘 시각화 라이브러리 ipytracer 개발기
 

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

NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기Jaeseung Ha
 
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
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스Sungik Kim
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 명신 김
 
병렬 프로그래밍
병렬 프로그래밍병렬 프로그래밍
병렬 프로그래밍준혁 이
 
ARTIK 710 IoT class 02
ARTIK 710 IoT class 02ARTIK 710 IoT class 02
ARTIK 710 IoT class 02정출 김
 
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013Esun Kim
 
Profiling - 실시간 대화식 프로파일러
Profiling - 실시간 대화식 프로파일러Profiling - 실시간 대화식 프로파일러
Profiling - 실시간 대화식 프로파일러Heungsub Lee
 
Windows Debugging Technique #2
Windows Debugging Technique #2Windows Debugging Technique #2
Windows Debugging Technique #2Wooseok Seo
 
Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나병걸 윤
 
[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규ChangKyu Song
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010Ryan Park
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10Ryan Park
 
Boost 라이브리와 C++11
Boost 라이브리와 C++11Boost 라이브리와 C++11
Boost 라이브리와 C++11OnGameServer
 
Python programming for Bioinformatics
Python programming for BioinformaticsPython programming for Bioinformatics
Python programming for BioinformaticsHyungyong Kim
 
2015 제2회 동아리 해커 세미나 - 병렬컴퓨팅 소개 (16기 김정현)
2015 제2회 동아리 해커 세미나 - 병렬컴퓨팅 소개 (16기 김정현)2015 제2회 동아리 해커 세미나 - 병렬컴퓨팅 소개 (16기 김정현)
2015 제2회 동아리 해커 세미나 - 병렬컴퓨팅 소개 (16기 김정현)khuhacker
 

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

파이선 실전공략-1
파이선 실전공략-1파이선 실전공략-1
파이선 실전공략-1
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
 
파이썬 데이터 분석 (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
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스
 
불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14 불어오는 변화의 바람, From c++98 to c++11, 14
불어오는 변화의 바람, From c++98 to c++11, 14
 
병렬 프로그래밍
병렬 프로그래밍병렬 프로그래밍
병렬 프로그래밍
 
Meteor IoT
Meteor IoTMeteor IoT
Meteor IoT
 
ARTIK 710 IoT class 02
ARTIK 710 IoT class 02ARTIK 710 IoT class 02
ARTIK 710 IoT class 02
 
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
사례를 통해 살펴보는 프로파일링과 최적화 NDC2013
 
Profiling - 실시간 대화식 프로파일러
Profiling - 실시간 대화식 프로파일러Profiling - 실시간 대화식 프로파일러
Profiling - 실시간 대화식 프로파일러
 
Windows Debugging Technique #2
Windows Debugging Technique #2Windows Debugging Technique #2
Windows Debugging Technique #2
 
Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나Hoons 닷넷 정기세미나
Hoons 닷넷 정기세미나
 
[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규
 
IPython
IPythonIPython
IPython
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
온라인 게임에서 사례로 살펴보는 디버깅 in NDC2010
 
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
온라인 게임에서 사례로 살펴보는 디버깅 in NDC10
 
Boost 라이브리와 C++11
Boost 라이브리와 C++11Boost 라이브리와 C++11
Boost 라이브리와 C++11
 
Python programming for Bioinformatics
Python programming for BioinformaticsPython programming for Bioinformatics
Python programming for Bioinformatics
 
2015 제2회 동아리 해커 세미나 - 병렬컴퓨팅 소개 (16기 김정현)
2015 제2회 동아리 해커 세미나 - 병렬컴퓨팅 소개 (16기 김정현)2015 제2회 동아리 해커 세미나 - 병렬컴퓨팅 소개 (16기 김정현)
2015 제2회 동아리 해커 세미나 - 병렬컴퓨팅 소개 (16기 김정현)
 

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

  • 1. 파이썬 데이터과학 이태영 se2n@naver.com 파이썬을 이용한 데이터 분석, 그리고 머신러닝 실전 입문 레벨-1
  • 2. 자료를 공개하는 이유 # 유명해지고 싶다 # 놀면 뭐하니 # 강의는 취미 # 특허도 취미 # 데이터사이언티스트 # 풀스택개발자 # 비씨카드 # 데이터분석왕 # 이태영
  • 3. 이태영 구글 ‘데이터과학 파이썬‘ 분야 SEO 국내 1위 (경력) 2015 BC FEP 실시간 승인 거래 분석 시스템 설계/개발/구축 2015 BC 집현전 대상 ‘오픈소스를 활용한 빅데이터 플랫폼 구축’ 2018 BC R&D Cell 최우수상 ‘AI 기반 서비스 플랫폼 구축’ 2020 BC 차세대프로젝트 Scalable FEP/MCI 시스템 구축 (특허/등록건) 2012 고객 단말기의 맥 어드레스 정보를 이용한 결제 방법 및 시스템 2013 고객 단말기의 맥 어드레스 정보를 이용한 결제 방법 및 시스템 2014 카드 상품 추천 방법 및 카드사 서버 2014 사용 업종 예측을 위한 카드 사용 패턴 분석 방법 및 수행 서버 2015 가맹점 개인화 추천 방법 및 가맹점 추천 서버 (논문) 2017 Scalable 네트워크 아키텍처와 In-memory 컴퓨팅에 기반한 실시간 결제 분석 시스템, 고려대. 2018 Abnormal Payment Transaction Detection Scheme based on Scalable Architecture and Redis Cluster, IEEE. (자격) 2020 Algorithms Specialization, Stanford University. 2020 Applied Data Science Specialization, University of Michigan. @관심사 : Scalable Architecture, Machine Learning, Object Detection, Visualization, Data Analysis, Pattern Recognition #BCCard #IT기획팀 #신기술 #전략기획 무슨 자격으로 강의를 하나요?
  • 4. 파이썬의 장점 • 문과도 잘 할 수 있다. • 이과도 잘 할 수 있다. • 60대도 20대보다 잘 할 수 있다. • 20대도 60대보다 잘 할 수 있다. • 영업도 IT보다 잘 할 수 있다. • IT도 영업보다 잘 할 수 있다. 데이터분석 파이썬 • C언어 기반 > 고성능 보장 • 쉬운 사용성 • 풍부한 라이브러리 • 규모의 경제학 • 얕은 수준으로 알고리즘을 알아도 구현 가능 (구글, 스택오버플로우 검색)
  • 5. 독서백편의자현(讀書百遍義自見) 삽질할 용기 강의자료 100번도 말고 딱 3번만 복습 그리고 궁금하면 질문! 모든 데이터셋은 https://github.com/sh2orc/datascience 등록되어 있습니다.
  • 6. 이번 과정을 통해 배울 지식 1. 파이썬 환경 • 개발환경 구축 2. 파이썬 답게 코딩 • 이터러블, 이터레이터, 제네레이터 • 조건문, 리스트 고급 표현식 • 람다(Lambda) • *args와 **kwargs 이용한 람다 • 파일 입출력, json과 pickle • 서울시 인구 통계 분석 실습 3. numpy • 기초 사용법, 배열 붙이기 • 기술통계, • 랜덤함수, 데이터샘플링, 비교연산 • 최소제곱법 (Least Squares) • 선형회귀식 (Linear Regression) 4. Pandas • 기초개념, 데이터프레임 • 컬럼명 변경, 컬럼기준 삭제 • 선택과 변경, 정렬 • 행/열 합계 • 시계열 관리 • 데이터프레임 Merge & Join • 그룹화 연산 • 피벗 테이블 5. 실전, 데이터분석 • 하루 승인 거래 건수 분석 및 평가 • 전문 거래 로그 분석 • 통계청 행정구역별 인구변화 분석 (2011~2020) • 코로나19(COVID-19) 감염자 분석 (Kaggle)
  • 8. 파이썬을 배우고 싶어요. 그런데 뭘로 코딩하지? Eclipse Jupyter 무겁지만 강력하다 빠르고 강력하다
  • 9. • 대화형 컴퓨팅으로 분석 프로그래밍 최적합 • 운영체제의 쉘 파일 시스템과 통합되어있음 • 웹기반의 대화형 노트북 지원으로 수식, 표, 그림 등을 표현 가능 • 가볍고 빠른 병렬컴퓨팅 엔진 이용 • 코딩과 문서화, 테스트까지 한 화면에 OK Jupyter Interactive computing python
  • 10. • python 3.6.10 설치 (윈도우는 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
  • 11. • 패키지 리스트 파일 이용한 설치 • 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
  • 12. 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 값을 설정
  • 13. 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
  • 14. Jupyter Notebook Web browser based Python IDE 코드를 타이핑 치고 Ctrl+Enter 결과 표시
  • 15. Jupyter Notebook 파이썬 스크립트 생성 • Notebooks – Python 선택
  • 16. Jupyter Notebook 파이썬 스크립트 생성 • Notebooks – Python 선택 클릭해서 저장되는 노트북 파일명 변경 Cell은 4가지 형식 존재 Cell 종류 설명 • Code : 파이썬 코드 • MarkDown : 일종의 마크업 언어. 엔하위키나 텀블러에서 사용 중 • Raw NBCovert : IPython 노트북 날 코딩(?) • Heading : <html>의 <head> 태그와 유사한 기능
  • 17. Jupyter Notebook 단축키 (Shortcut) • Edit Mode : 셀 안에서 사용하는 단축키 • Command Mode : 셀 경계에서 사용하는 단축키 • h 를 누르면 기본 단축키에 대해 어느 정도 나온다. Edit mode 단축키Command mode 단축키 마우스 클릭하고
  • 18. 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 노트북 파일 저장
  • 19. 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 / 방향키 아래 다음 셀로 이동
  • 20. Jupyter Notebook Cell : Markdown • Markdown language 기반으로 Document 작성 (Wikipedia처럼 작성 방식) • 코드에 대한 설명이 가능하다. • 수학수식 표현도 가능 (Mathjax) 내용을 적고 Ctrl+Enter
  • 21. Jupyter Notebook Cell : Markdown • 제목(Head 태그) # 텍스트 # 하나를 쓰면 HTML의 <h1> 태그 # 두개를 쓰면 HTML의 <h2> 태그. 최대 6개까지 쓸 수 있다. • 리스트 (li 태그) • 번호 없는 리스트 : -텍스트 , +텍스트, *텍스트 • 번호 있는 리스트 : 숫자.텍스트 • 기울인 글씨(Italic 태그) : _텍스트_ , *텍스트* • 굵은 글씨(Strong 태그) : __텍스트__ , **텍스트** • 인용(cite) : >텍스트 • 인라인 링크 : [텍스트](링크) • 수평선(hr 태그) : --- , *** , ___
  • 22. Jupyter Notebook Cell : Code • 파이썬의 코드를 각 셀에 원하는 만큼을 작성하여 실행하면 메모리 상에 반영된다. • 위, 아래 위치가 달라도 실행한 스텝 번호(In [번호])가 높을 수록 최근에 수행된 영역이다. 방향 버튼을 이용하여 Cell의 위치를 변경 가능
  • 23. 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번호 구간대 명령어를 파일로 저장
  • 24. Jupyter Notebook Magic Keyword (매직 명령어) • 자주 사용하는 IPython 매직 명령어 • %(명령어) : 셀 내의 라인 독립 실행 • %%(명령어) : 셀 내의 전체 내용 관련 실행
  • 25. Jupyter Notebook Magic Keyword (매직 명령어) : TIP • (리눅스/유닉스만) %%writefile으로 스크립트 저장 후 %run으로 실행하려면 파이썬 스크립트에 한글이 포함될 때는 #!(샤방) 파이썬 패스, 언어 타입 정의 필요하다. #!/usr/bin/python #-*- coding: utf-8
  • 26. Jupyter Notebook 운영체제와 함께 사용하기 • IPython에서 운영체제의 자체 명령어를 실행하기 위해서는 !(명령어)로 수행
  • 27. Jupyter Notebook 운영체제와 함께 사용하기 • !(명령어)로 수행된 출력결과를 IPython의 데이터로 사용 가능
  • 28. Jupyter Notebook ipdb 디버깅을 이용한 코드 분석 • 매직 명령어 %debug 혹은 %%debug
  • 29. 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 디버깅 종료
  • 30. Jupyter Notebook ipdb 디버깅을 이용한 코드 분석 • h (help) 명령어
  • 31. 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()
  • 32. • 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. 2. 파이썬 답게 (pythonic) 코딩 데이터 분석을 위한 코딩 기법
  • 34. 파이썬의 장점 • 문과도 잘 할 수 있다. • 이과도 잘 할 수 있다. • 60대도 20대보다 잘 할 수 있다. • 20대도 60대보다 잘 할 수 있다. • 영업도 IT보다 잘 할 수 있다. • IT도 영업보다 잘 할 수 있다. 이것을 알아두면 고급 개발자 • 이터러블 • 이터레이터 • 제네레이터 • One Line 조건문 • 리스트 표현식(List Comprehension) • 람다함수 (lambda) • *args, **kwargs 매개변수 • 파일 입출력 • json, pickle
  • 35. 파이썬 답게 코딩하기 이터러블(iterable) • 파이썬에서는 이터러블(iterable) 객체 개념 존재 • 이터러블은 내부적으로 __iter__라는 메소드(함수)를 가지는 객체 • 이터러블은 3가지 특징 • 반복 처리 가능 (예를 들면 문자열이나 파일) • for~loop에서 오른쪽에 정의 가능 • iter(이터러블)통해 iterator 객체가 할당 for 임시변수 in iterable(리스트, 튜플, 디셔너리, 함수 등): 구현 코드 for x in [1,2,3,4,5]: print(x) for x in range(5): print(x) for x in "hello": print(x)
  • 36. 파이썬 답게 코딩하기 이터레이터(iterator) • 이터러블(iterable)은 ’순차적으로 접근을 할 수 있는’ 객체들의 통칭 • 이터레이터는(iterator)는 이터러블을 이용하여 변환한 객체 A = iter ('hello’) next(A) #h next(A) #e next(A) #l next(A) #l next(A) #o next(A) --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-8-2547a3b71e0f> in <module> ----> 1 next(A) StopIteration:
  • 37. 파이썬 답게 코딩하기 제네레이터(generator) • 표현식 혹은 함수를 통해 정의되는 이터레이터(iterator) • return 키워드가 아닌 yield 키워드가 사용되면 제네레이터 • yield를 이용하면 함수의 끝이 아닌 호출 이후 계속 처리를 의미 def g(): print('one’) yield 1 #첫번째 next 호출 시 여기까지 처리 print('two’) yield 2 #두번째 next 호출 시 여기까지 처리 print('three’) yield 3 #세번째 next 호출 시 여기까지 처리 _ = g() next(_) next(_) next(_) #반복문 처리 시 활용 def g(): A = [1,2,3,4,5] for _ in A: yield _ for _ in g(): print( _ * 2)
  • 38. 파이썬 답게 코딩하기 이터러블(iterable), 이터레이터(iterator), 제네레이터(generator) 관계 제네레이터 (generator) 이터레이터 (iterator) 이터러블 (iterable) always is always is iter() next() lazy produce next value {list, set, dict} 등 컨테이너 제네레이터 함수/표현식 for-loop iterable
  • 39. 파이썬 답게 코딩하기 (파이썬 다운) 한줄 조건문 • 파이썬의 조건문은 변수 할당 시점 한줄로 작성이 가능 (if statement in one line) • 이 경우는 if-else 형식으로 정의 되어야 하며 값표현은 왼쪽, 조건은 오른쪽 표현 특징 (왼손잡이 사고전환) • 오른쪽에 조건이 정의될 경우 if만 단독적으로 사용 불가하며 else가 꼭 정의되어야 함 b = '참' if (True조건) else '거짓' b = '참' if (True조건) else '거짓' #거짓 조건일 경우 다시 조건을 넣을 수 있다. b = '참' if (True조건) else ('거짓>참' if (False-True조건) else '거짓>거짓’) b = '참' if (True조건) else '거짓>참' if (False-True조건) else '거짓>거짓’ #괄호를 없앨 수 있음 #파이썬의 라인의 끝을 구분자를 작성하고 다음 라인으로 내릴 수 있다. b = '참' if (True조건) else '거짓>참' (False-True조건) else '거짓>거짓' • else에 추가적인 조건을 계속 넣을 수 있음
  • 40. 파이썬 답게 코딩하기 (파이썬 다운) 한줄 조건문 • 오른쪽에 표현식이 오는 One line 조건문은 백슬래쉬 키를 이용하여 라인을 구분하면 보기 편함 • 이 조건 표현식은 리스트 표현식, 람다문법 등 파이썬의 핵심 표현식으로 알아두는게 좋음 def confirm(x): return '1입니다' if x == 1 else '5입니다' if x == 5 else '1도 5도 아닙니다.’ confirm(1) 1입니다. confirm(3) 1도 5도 아닙니다.
  • 41. 파이썬 답게 코딩하기 리스트 표현식 • 파이썬에서 리스트는 [ ] 대괄호 안에 쉼표 , 구분자로 분리 A = ['ABC','DEF','HIG’] # A값 ['ABC','DEF','HIG’] A = [1,2,3,4,5] # A값 [1,2,3,4,5] A[시작위치:끝위치] # 슬라이싱범위 (시작위치≤ A < 끝위치) A[시작위치:] # 시작위치부터 끝까지 슬라이싱 A[:끝위치] # 끝위치-1까지 슬라이싱 A = [1,2,3,4,5] A[:2] # [1,2] 출력 • 리스트는 슬라이싱 가능 A.append(6) # A값 [1,2,3,4,5,6] del(A[0]) # A값 [2,3,4,5,6] • 리스트는 추가하고 삭제 가능
  • 42. 파이썬 답게 코딩하기 (파이썬 다운) 리스트 표현식 • 리스트, 튜플, 딕셔너리 등 데이터구조에서 for ~ in 표현식으로 데이터를 가공이 가능 [expression for member in iterable (if conditional)] [ 임시변수_표현 for 임시변수 in 이터러블 ] [ 임시변수_표현 for 임시변수 in 이터러블 if 임시변수조건 ] # if 조건만 있을 경우 [ 임시변수_True표현 if 임시변수_True조건 else 임시변수_False표현 for 임시변수 in 이터러블] • 만약 if-else 조건을 넣을 순간이 온다면 if 조건은 오른쪽이 아닌 임시변수_표현 영역에 구현 [ 임시변수_표현 for 임시변수 in 이터러블 ] 한줄 조건문
  • 43. 파이썬 답게 코딩하기 (파이썬 다운) 리스트 표현식 A = list(range(10)) # [0,1,2,3,4,5,6,7,8,9] 할당 #파이썬에서 _ 문자를 변수명으로 사용 가능함. 쓰고 버리는 의미 없는 임시변수 표현 B = [ _ for _ in A] # [0,1,2,3,4,5,6,7,8,9] 할당 C = [ _ for _ in A if _ > 5] # [6,7,8,9] 할당 = 5보다 큰 값 할당 (필터링 역할) D = [ _ if _ > 5 else 0 for _ in A ] # [0,0,0,0,0,6,7,8,9] = 5보다 큰 경우 그대로, 작은 경우 0으로 초기화 • 리스트 표현식 예제 [ _ for _ in A if (조건1) and (조건2)] [ _ for _ in A if (조건1) if (조건2) ] • 조건을 and 나 or로 묶을 수 있음 • 리스트 표현식에서 if를 여러번 쓰는 것은 and와 같은 처리를 의미 [ _ for _ in A if _ > 5 and _ % 2 == 0] # [6,8] 출력
  • 44. 파이썬 답게 코딩하기 함수(function) # F(n) = F(n-1) + F(n-2) 단, n>2일 경우 def F(n): if n <= 2: return 1 else: return F(n-1) + F(n-2) R = [ F(n) for n in range(1,10)] print(R) #[1, 1, 2, 3, 5, 8, 13, 21, 34] • 함수는 def를 이용하여 선언 • 피보나치 수열 정의를 이용하여 구현 예제 the sequence starts with F1 = F2 = 1, and the recurrence Fn=Fn−1 +Fn−2 (n > 2)
  • 45. 파이썬 답게 코딩하기 (파이썬 다운) 람다(lambda) 함수 def 함수명(임시변수): return (임시변수 표현식) • 파이썬에서 가장 강력한 기능 중 하나 • 익명함수 (Anonymous Function)라고도 부르며, 함수 정의를 한 줄로 생략하는 방식 • 일반적으로 함수가 아래처럼 정의된다면, 함수명 = lambda 임시변수 : (임시변수 표현식) 함수명 = lambda 임시변수 : (True조건 표현식) if 조건 else (Flase조건 표현식) • lambda 표현식으로 함수명을 변수에 정의하듯 선언 • if-else를 통해 표현이 되며, if 가 정의되면 else 조건도 함께 작성되어야 합니다. return 되는 값 return 되는 값 return 되는 값
  • 46. 파이썬 답게 코딩하기 (파이썬 다운) 람다(lambda) 함수 • lambda 예제 A = lambda x : x * 2 A(5) #10 값 F = lambda n : F(n-1)+F(n-2) if n > 2 else 1 R = [ F(n) for n in range(1,10)] print(R) #[1, 1, 2, 3, 5, 8, 13, 21, 34] • 피보나치 수열 예제 • map 활용 예제 • map은 정의된 함수 F가 있다면, 이터러블(iterable)에 함수 F를 적용한 이터레이터(iterator)로 반환 map(function, iteratble) A = [1,2,3,4,5] F = lambda n : F(n-1)+F(n-2) if n > 2 else 1 R = map( F, A ) # R을 출력하면 <map at 0x21d324ab848> [ _ for _ in R ] #[1, 1, 2, 3, 5]
  • 47. 파이썬 답게 코딩하기 (파이썬 다운) 람다(lambda) 함수 • lambda 예제 A = lambda x : x * 2 B = lambda x : x * 3 C = lambda x : x * 4 D = lambda x : x * 5 L = [A, B, C, D] for f in L: print( f(2) ) • 2 값에 대해 L 함수 리스트로 처리할 경우 4 6 8 10 F = lambda n : [ f(n) for f in L ] F(2) #[4, 6, 8, 10] • 함수 L에 대한 반복 처리하는 lambda 함수를 다시 정의하면,
  • 48. 파이썬 답게 코딩하기 (파이썬 다운) 람다(lambda) 함수 • 문자열을 Upper-case, Lower-case, Capitalize 시키는 함수 def process(string, code): func_dict = { 'U' : lambda x : x.upper(), 'L' : lambda x : x.lower(), 'C' : lambda x : x.capitalize()} F = func_dict[code] return F(string) def process(string, code): return { 'U' : lambda x : x.upper(), 'L' : lambda x : x.lower(), 'C' : lambda x : x.capitalize() } [code] (string) • 위 함수를 좀더 줄여쓰면 아래처럼 직접 딕셔너리로 접근 후 함수 호출 가능 process('hello',’U’) # HELLO process(‘HELLO',’L’) # hello process(‘hello,’C’) # Hello
  • 49. 파이썬 답게 코딩하기 (파이썬 다운) *args와 **kwargs 이용한 람다 • *args 표현식 함수의 매개변수에 * 문자는 임의의 복수의 매개변수가 오는 것으로 정의 • **kwargs 표현식 함수의 매개변수에 ** 문자는 임의의 key=value 형태의 복수의 매개변수가 오는 것으로 정의 F = lambda *x : ' '.join( x ) # 문자열을 붙여주는 함수 F('파이썬','코딩','쉽네') # '파이썬 코딩 쉽네' F = lambda **x : [ (v, k) for k, v in x.items()] # key, value를 서로 바꿔서 dictionary 생성 D = ( A = '파이썬', B = '코딩', C='쉽네') # {'파이썬':'A', '코딩':'B', '쉽네':'C'} D['파이썬'] # 'A' 출력 F = lambda **x : sum(x['data']) if 'type' in x and x['type'] == 'sum' else 0 F(type='sum', data=[1,2,3,4,5]) F(data=[1,2,3,4,5]) F(type='mul', data=[1,2,3,4,5]) • *kwargs를 이용한 변수가 정의되었을 경우 처리 예제
  • 50. 파이썬 답게 코딩하기 파일 입출력 • 파일 처리는 직접 object를 생성하기 보다 with 문을 사용 권고 • with 문에서 선언된 오브젝트는 Context Manager 의해 구문이 끝나는 시점 자동으로 메모리 해제. close() 함수를 호출하지 않아도 됨. with open(파일명, 'rwa+') as 파일오브젝트변수명: 코드구현 with open('student', 'r') as fr: print( fr.readline() ) • student 파일 읽기 예제 라인별 이름;국어점수;영어점수;수학점수;과학점수 태서연;54;72;60;78 F = lambda x : x.split(';')[1:] F('태서연;54;72;60;78') • 이름(첫번째)를 제외한 숫자 문자열들만 추출 ['54' ,'72', '60', '78']
  • 51. 파이썬 답게 코딩하기 (파이썬 다운) 파일 입출력 • 입력 문자열을 숫자로만 추출하기 (list comprehension) F = lambda x : [ int( _ ) for _ in x.split(';')[1:] ] F('태서연;54;72;60;78') [54 ,72, 60, 78] F = lambda x : sum([ int( _ ) for _ in x.split(';')[1:] ]) F('태서연;54;72;60;78') • 입력 문자열을 합계 264 F = lambda x : ( x.split(';')[0] , sum([ int( _ ) for _ in x.split(';')[1:] ]) ) name, total = F('태서연;54;72;60;78') print( name, total ) • 이름, 과목별 점수 합계 리턴 태서연 264
  • 52. 파이썬 답게 코딩하기 (파이썬 다운) 파일 입출력 • 입력 문자열을 미리 split 하여서 리스트로 넘긴다고 가정 F = lambda L : [ int( _ ) for _ in L[1:] ] F('태서연;54;72;60;78'.split(';')) [54 ,72, 60, 78] F = lambda L : ( L[0] , sum([ int( _ ) for _ in L[1:] ]) ) name, total = F('태서연;54;72;60;78'.split(';')) print( name, total ) • 이름, 점수 합계를 리턴하는 방법 태서연 264 F = lambda L, T : ( L[0] , sum([ int( _ ) for _ in L[1:] ]) ) if T == 'sum' else ( L[0] , sum([ int( _ ) for _ in L[1:] ]) / len(L[1:]) ) if T == 'avg' else ( L[0] , None ) • 타입별 (이름, 합계), (이름, 평균)을 나타내는 함수
  • 53. 파이썬 답게 코딩하기 (파이썬 다운) 파일 입출력 • 파일을 읽어서 이름;합계;평균을 내는 student_result 파일로 저장 with open('student','r') as fr, open('student_result','w') as fw: for line in fr: name, total_sum = F(line.split(';'), 'sum') name, total_avg = F(line.split(';'), 'avg') # 문자열 앞에 f를 붙이면 문자열 내부에 { }를 이용하여 변수를 바인딩 할 수 있음. f-string result = f"{name};{total_sum};{total_avg}n" fw.write(result) • 저장된 내용 확인 with open('student_result') as fr: print(fr.readline()) print(fr.readline()) print(fr.readline())
  • 54. 파이썬 답게 코딩하기 (파이썬 다운) 데이터를 json 파일/텍스트로 변환 • json.dumps( dict ) - 딕셔너리를 json 문자열로 변환 가능 • json.dump( dict, file object ) - 딕셔너리를 json 문자열 형태로 file object에 저장 import json person_dict = {} # 딕셔너리 with open('student','r') as fr, open('student_json', 'w') as fw: for line in fr: data = line.strip().split(';') #불필요 공백 제거 후 ; 문자로 문자열 분리 name = data[0] #이름 # kor, eng, mat, sci = int(data[1]), int(data[2]), int(data[3]), int(data[4]) kor, eng, mat, sci = ( int( _ ) for _ in data[1:] ) person_dict[name] = { '국어' : kor, '영어' : eng, '수학' : mat, '과학' : sci } json.dump( person_dict, fw) # 딕셔너리를 JSON으로 변환하여 파일로 저장 json_data = json.dumps( person_dict ) # 딕셔너리를 JSON 문자열로 변환 print(json_data) # JSON 문자열 확인
  • 55. 파이썬 답게 코딩하기 (파이썬 다운) 파이썬 오브젝트를 json 텍스트로 변환 • json dump(s)에 ensure_ascii = False를 지정해야 한글들이 유니코드로 변환되는 것을 방지 • json dump(s)에 indent = 숫자를 지정하면 숫자만큼 깔끔하게 인덴트 추가 import json person_dict = {} # 딕셔너리 with open('student','r') as fr for line in fr: data = line.strip().split(';') #불필요 공백 제거 후 ; 문자로 문자열 분리 name = data[0] #이름 kor, eng, mat, sci = ( int( _ ) for _ in data[1:] ) person_dict[name] = { '국어' : kor, '영어' : eng, '수학' : mat, '과학' : sci } json_data = json.dumps( person_dict, ensure_ascii=False, indent=4 ) # 한글 보존, indent 추가 print(json_data)
  • 56. 파이썬 답게 코딩하기 (파이썬 다운) json 텍스트를 파이썬 오브젝트로 변환 import json with open('student_json', 'r' , encoding='UTF-8-sig') as fr json_data = json.load(fr) print( json_data['태서연'] ) # {'국어': 54, '영어': 72, '수학': 60, '과학': 78} with open('student_json', 'r' , encoding='UTF-8-sig') as fr json_text = ''.join(fr.readlines()) json_data = json.loads(json_text) print( json_data['태서연'] ) # {'국어': 54, '영어': 72, '수학': 60, '과학': 78} • json.loads( 텍스트 ) - JSON 형태의 텍스트를 파이썬 오브젝트로 변환 • json.load( file object ) - 파일에 저장된 JSON 텍스트를 파이썬 오브젝트로 변환
  • 57. 파이썬 답게 코딩하기 (파이썬 다운) pickle - 데이터 직렬화 저장/로딩 import json import pickle with open('student_json', 'r' , encoding='UTF-8-sig') as fr: json_data = json.load(fr) with open('student_pickle', 'wb') as fw: pickle.dump(json_data, fw) with open('student_pickle', 'rb') as fr: pickle_data = pickle.load(fr) print( pickle_data['태서연'] ) # {'국어': 54, '영어': 72, '수학': 60, '과학': 78} • 파이썬에서는 pickle 이라는 패키지를 통해 데이터를 직렬화하여 바이너리 형태로 저장 • 사용법은 json 패키지와 동일하게 dump(s), load(s) 함수를 통해 저장/로딩
  • 58. 파이썬 답게 코딩하기 서울시 인구 통계 분석 (실습) • seoul_people_report (CSV) 파일을 기반으로 구명을 key 값을 가지는 딕셔너리로 변경 • 구별 '외국인 비율', '65세이상고령자 비율'을 계산 후 각각 key(외국인비율, 고령자비율)에 저장 자치구,전체,남자,여자,외국인,65세이상고령자 합계,10013781,4874995,5138786,280126,1518239 종로구,161984,78271,83713,10767,28073 중구,136469,66769,69700,10294,23794 용산구,246165,119961,126204,16586,39439 성동구,307193,149891,157302,8151,44728 광진구,365990,176226,189764,15573,48989 동대문구,362793,178202,184591,16637,60367 중랑구,400678,198122,202556,5059,66764 성북구,454532,218561,235971,12038,72172 강북구,316750,154141,162609,3765,61660 도봉구,333495,162774,170721,2257,60023 노원구,535495,258696,276799,4458,82682 은평구,482509,231953,250556,4490,82245 서대문구,325875,154502,171373,13233,53038 마포구,386086,181204,204882,11516,53283 양천구,460532,226109,234423,4193,62761 강서구,595703,288134,307569,6401,85992 구로구,438308,218970,219338,32471,67432 금천구,251370,128643,122727,18787,38508 영등포구,404766,202617,202149,32863,59373 동작구,407802,196943,210859,12788,63378 관악구,516662,258982,257680,17288,76664 서초구,434801,207877,226924,4233,58332 강남구,549898,263163,286735,5094,72602 송파구,680883,329058,351825,6788,89539 강동구,457042,225226,231816,4396,66401 seoul_people_report with open('seoul_people_report', 'r' , encoding='UTF-8-sig') as fr: raw_list = [ _.strip() for _ in fr.readlines() ] #라인별로 분할 raw_split = [_.split(',') for _ in raw_list ] #각 라인을 , 로 분할 district_dict = {} for data in raw_split[1:]: #상단 헤더를 제외 ds_name = data[0] _1, _2, _3, _4, _5 = ( int(_) for _ in arr[1:]) district_dict[ ds_name ] = {'전체': _1, '남자': _2, '여자': _3, '외국인': _4, '고령자': _5} for k, v in district_dict.items(): # 실습 구현 # district_dict['종로구']['외국인비율'] # district_dict['종로구']['고령자비율'] #json 형태로 seoul_people_json 으로 저장 코드 실습
  • 59. 파이썬 답게 코딩하기 서울시 인구 통계 분석 (실습) • lambda 식을 이용하여 딕셔너리 키 값, 기준값을 받아서 조건을 충족하면 그대로, 미충족 시 None • 고령자 비율 15%가 넘고, 외국인 비율이 5%를 넘는 구의 인력현황 출력 및 저장 자치구,전체,남자,여자,외국인,65세이상고령자 합계,10013781,4874995,5138786,280126,1518239 종로구,161984,78271,83713,10767,28073 중구,136469,66769,69700,10294,23794 용산구,246165,119961,126204,16586,39439 성동구,307193,149891,157302,8151,44728 광진구,365990,176226,189764,15573,48989 동대문구,362793,178202,184591,16637,60367 중랑구,400678,198122,202556,5059,66764 성북구,454532,218561,235971,12038,72172 강북구,316750,154141,162609,3765,61660 도봉구,333495,162774,170721,2257,60023 노원구,535495,258696,276799,4458,82682 은평구,482509,231953,250556,4490,82245 서대문구,325875,154502,171373,13233,53038 마포구,386086,181204,204882,11516,53283 양천구,460532,226109,234423,4193,62761 강서구,595703,288134,307569,6401,85992 구로구,438308,218970,219338,32471,67432 금천구,251370,128643,122727,18787,38508 영등포구,404766,202617,202149,32863,59373 동작구,407802,196943,210859,12788,63378 관악구,516662,258982,257680,17288,76664 서초구,434801,207877,226924,4233,58332 강남구,549898,263163,286735,5094,72602 송파구,680883,329058,351825,6788,89539 강동구,457042,225226,231816,4396,66401 seoul_people_report #특정 기준 값이 기준치를 넘으면 그대로 출력, 미달이면 None F = lambda dataset, k, std : dataset[k] if dataset[k] > std else None for key, val in district_dict.items(): R = F(val, '고령자비율', 15) if R is not None: print(k, R) district_list = [] #실습코딩 #고령자 비율 15% 넘고, 외국인 비율 5%를 넘는 구의 인력현황 #district_list에 위 조건에 맞는 딕셔너리들을 저장 #district_list는 json을 이용하여 seoul_people_output 파일로 저장 코드 실습
  • 61. 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)
  • 62. Numpy 기초 사용법 • 스칼라/벡터/행렬 • 스칼라는 number • 벡터(vector)는 숫자들의 list • 행렬(matrix)는 숫자들의 array(rows, columns)
  • 63. 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]])
  • 64. 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])
  • 65. 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)
  • 66. 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]])
  • 67. 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]]])
  • 68. 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.]]])
  • 69. 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])
  • 70. 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])
  • 71. 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 배열의 데이터들에 대해 선택될 수 있는 확률 지정
  • 72. 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. ]])
  • 73. 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으로 나눈 뒤의 나머지 추출
  • 74. 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 좌표에 어떤 데이터가 입력되는지 확인하고 눈으로 보는 데 의의두자!
  • 75. Numpy 최소제곱법 : 선형회귀 • 최소제곱법 (Method of Least Squares) • 함수 값과 측정 값의 차이인 오차를 제곱한 것의 합이 최소가 되는 함수 Y = F(X)를 구하는 방법 • f(x) = ax + b의 경우 f(x)를 최소화 하도록 a, b를 결정 짓는 방법 • σ𝑖=1(𝑦𝑖 − 𝑎𝑥𝑖 − 𝑏)2 • 각 데이터 좌표에서 최적함수까지의 거리 구함 • 최적의 함수라면, 이 차이가 가능한 한 최소화 • 최소제곱법은 이 편차를 최소화하기 위한 방법 • 이렇게 나온 선을 최소제곱선 혹은 선형회귀선 측정값 𝑦𝑖 𝑦𝑡𝑟𝑢𝑒 상수항 α 종속변수 𝑦 독립변수 𝑥 오차𝑒𝑖
  • 76. 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(x, 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])
  • 77. Numpy 선형회귀(Linear Regression) • polyfit과 poly1d를 이용한 선형회귀 • np.polyfit(x array, y array, degree) : 주어진 측정 값들로 다항식의 계수를 구함 • x array, y array값을 입력, degree는 다항식의 차수 • x array는 좌표에서 X축을 구성하는 데이터셋, y array는 좌표에서 Y축을 구성하는 데이터셋 • 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 함수로 연산
  • 78. Numpy 선형회귀(Linear Regression) 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(x, 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])
  • 79. 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()
  • 81. 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() # 그래프로 출력
  • 82. 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(열)
  • 83. 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
  • 84. 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
  • 85. 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)
  • 86. Pandas DataFrame 생성 • CSV 형식 파일을 읽어 들여 DataFrame 생성 • pd.read_csv(path, sep='구분자', names=['컬럼명',..]) : 파일로부터 DataFrame 생성 • 데이터셋은 github.com/sh2orc/datascience에서 데이터셋 다운로드 가능 #컬럼 헤더가 없는 파일의 경우는 name= 옵션을 통해 지정해줄 수 있다. df = pd.read_csv('trns_msg_info', names=['MSG_CODE', 'MSG_NAME'], dtype=str) MSG_CODE MSG_NAME 0 0100 MS승인요청 1 0110 MS승인응답 2 0300 IC승인 요청 3 0310 IC승인 응답 4 0420 MS승인취소 요청
  • 87. 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 우체국
  • 88. Pandas Column명 변경 • DataFrame의 컬럼명 Rename 3가지 방법 • pd.DataFrame.columns = [ '칼럼1', '칼럼2', … , ] 이용 • pd.DataFrame.rename( { 'OLD칼럼명' : 'NEW칼럼명', …, }, axis=1) 이용 • pd.DataFrame.rename(columns={ 'OLD칼럼명' : 'NEW칼럼명', …, }) 이용 df = pd.read_csv('trns_msg_info', 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승인취소 요청
  • 89. Pandas apply 함수 - 컬럼(Series) 데이터 변경 • 특정 컬럼의 값들을 함수를 매핑하여 고속으로 값들을 변조나 생성 가능 (강력한 기능 중 하나) • df['컬럼명'].apply(함수) 방식을 통해 처리하며 일반적으로 함수에는 lambda 식으로 표현 • .applymap() 존재하며 이것은 대상 데이터프레임의 전체 요소마다 함수를 적용하는 것이다. #MSG_NAME의 값들 중 빈칸들을 모두 제거하고자 할 때 df['MSG_NAME'] = df.MSG_NAME.apply( lambda x: x.replace(' ','') ) # MSG_NAME이 IC로 시작하는지 여부를 컬럼명 'IS_IC'로 생성 df['IS_IC'] = df.MSG_NAME.apply( lambda x: True if x[:2] == 'IC' else False ) CODE MSG_NAME 0 0100 MS승인요청 1 0110 MS승인응답 2 0300 IC승인요청 3 0310 IC승인응답 4 0420 MS승인취소요청 CODE MSG_NAME IS_IC 0 0100 MS승인요청 False 1 0110 MS승인응답 False 2 0300 IC승인요청 True 3 0310 IC승인응답 True 4 0420 MS승인취소요청 False
  • 90. df = pd.read_csv('trns_msg_info', 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로 지정 시 해당 데이터 컬럼이 데이터의 축이 된다.
  • 91. Pandas DataFrame Index • index 초기화 • reset_index() : 기존 index를 컬럼으로 위치시키고, 새로운 index를 생성한다. df = pd.read_csv('trns_msg_info', 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승인취소 요청
  • 92. Pandas 열(COLUMN)과 행(ROW) 삭제 • pd.DataFrame.drop([label, …, ], axis=0 또는 1) • 행(ROW) 삭제 - label에 삭제할 row의 index들을 입력 • 행(Colum) 삭제 - label에 삭제할 column들을 입력. 이 때 axis=1로 지정 df = pd.read_csv('trns_msg_info', 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승인취소 요청
  • 93. Pandas 열(COLUMN)과 행(ROW) 삭제 • 특정 컬럼 기준으로 삭제 방법 • 칼럼을 index로 지정하고, 삭제할 대상을 각각 하드코딩 • 칼럼을 index를 리스트로 추출하여, 삭제할 대상에 입력 df = pd.read_csv('trns_msg_info', 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 삭제
  • 94. 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
  • 95. 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
  • 96. 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
  • 97. 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
  • 98. 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
  • 99. 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
  • 100. 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
  • 101. 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')
  • 102. 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 각 달의 첫날
  • 103. 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')
  • 104. 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
  • 105. 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
  • 106. 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
  • 107. 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
  • 108. 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
  • 109. 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
  • 110. Pandas pivot 테이블 • 데이터프레임을 특정 기준으로 재구성을 하는 방법 • .pivot() 메소드, .pivot_table() 메소드가 있으나 pivot_table를 많이 씀 • .pivot_table(index=['칼럼명',…], columns=['컬럼명',...], aggfunc=[함수], fill_value=...) • index : 피벗 테이블 생성 시 인덱스 영역으로 그룹핑할 대상 • colums : 피벗 테이블 생성 시 컬럼 영역으로 그룹핑할 대상 • aggfunc : 그룹핑한 이후 처리되는 함수, 기본적으로 np.means(평균)가 적용 df = pd.read_csv('student_exam_result') df.head() df.columns Index(['이름', '과목', '점수', '재시험회수', '합격여부', '건수'], dtype='object') 이름 과목 점수 재시험회수 합격여부 0 이혜원 과학 90 3 Passed 1 김현서 과학 75 1 Passed 2 박지유 국어 51 2 Failed 3 태시아 국어 51 2 Failed 4 김수아 수학 32 2 Failed
  • 111. Pandas pivot 테이블 # aggfunc는 default로 np.means 지정 숫자인 '재시험회수', '점수'의 평균이 출력됨 df.pivot_table(index=['합격여부']) 재시험회수 점수 합격여부 Failed 2.079439 47.892523 Passed 1.891192 84.284974 # index로 '과목'과 '합격여부'를 지정하면 멀티 Index로 지정됨 df.pivot_table(index=['과목', '합격여부']) 재시험회수 점수 과목 합격여부 과학 Failed 2.156250 65.281250 Passed 2.014706 85.911765 국어 Failed 2.261905 59.500000 Passed 1.793103 84.379310 수학 Failed 2.000000 42.491525 Passed 1.756098 83.463415 영어 Failed 2.012987 38.103896 Passed 2.043478 80.739130 철학 Failed 2.000000 55.000000 Passed 1.666667 84.000000
  • 112. Pandas pivot 테이블 # columns에 지정된 컬럼은 카테고리화 되는데, 이 때 수치 값을 가지는 컬럼의 하위 그룹핑이 됨 # 재시험회수는 1,2,3 값으로 분포되어 있으며, columns에 지정되어 '점수' 하위 컬럼으로 재매핑 df.pivot_table(index=['과목', '합격여부'], columns=['재시험회수']) 점수 재시험회수 1 2 3 과목 합격여부 과학 Failed 64.375000 66.181818 65.076923 Passed 86.120000 86.529412 85.307692 국어 Failed 56.625000 60.400000 60.000000 Passed 84.666667 85.000000 82.666667 수학 Failed 42.434783 44.461538 41.434783 Passed 85.578947 81.307692 82.111111 영어 Failed 38.500000 37.214286 38.720000 Passed 82.750000 80.214286 80.600000 철학 Failed 54.000000 63.500000 39.000000 Passed 84.000000 84.000000 NaN df['재시험회수'].unique() array([3, 1, 2], dtype=int64)
  • 113. Pandas pivot 테이블 #df.pivot_table(index=['과목', '합격여부'], columns=['재시험회수']) df.pivot_table(index=['과목'], columns=['합격여부','재시험회수']) # 합격여부를 컬럼으로 옮겨서 표현 점수 합격여부 Failed Passed 재시험회수 1 2 3 1 2 3 과목 과학 64.375000 66.181818 65.076923 86.120000 86.529412 85.307692 국어 56.625000 60.400000 60.000000 84.666667 85.000000 82.666667 수학 42.434783 44.461538 41.434783 85.578947 81.307692 82.111111 영어 38.500000 37.214286 38.720000 82.750000 80.214286 80.600000 철학 54.000000 63.500000 39.000000 84.000000 84.000000 NaN • 멀티 인덱스가 가능한 것처럼 멀티 컬럼도 가능
  • 114. Pandas pivot 테이블 • 각 컬럼들의 수치 연산은 axis=1 옵션을 통해 처리 가능 (미입력시 Row 기준 합계) tf = df.pivot_table(index=['과목'], columns=['합격여부','재시험회수'], aggfunc=len)[['점수']] tf['합계'] = tf['점수'].sum(axis=1) #새로운 컬럼 '합계'로 결과 저장 점수 합계 합격여부 Failed Passed 재시험회수 1 2 3 1 2 3 과목 과학 8.0 11.0 13.0 25.0 17.0 26.0 100.0 국어 8.0 15.0 19.0 24.0 22.0 12.0 100.0 수학 23.0 13.0 23.0 19.0 13.0 9.0 100.0 영어 24.0 28.0 25.0 4.0 14.0 5.0 100.0 철학 1.0 2.0 1.0 1.0 2.0 NaN 7.0
  • 115. • stack - 상단 헤더 컬럼들을 index 기준으로 각각 재그룹화 (기존 인덱스의 하위 레벨로 그룹핑) • unstack - 멀티 인덱스를 컬럼 기준으로 재그룹화 시키는 방법 (기존 헤더의 하위 레벨로 그룹핑) _f = pd.DataFrame([[1,'A'], [2,'B']], columns=['C1','C2'], index=['I1','I2']) C1 C2 1 A 2 B I1 I2 _f.stack() I1 C1 1 C2 A I2 C1 2 C2 B dtype: object C1 C2 1 A 2 B I1 I2 C1 C2 인덱스 인덱스 values in Series DataFrame Pandas stack과 unstack
  • 116. • stack - 상단 헤더 컬럼들을 index 기준으로 각각 재그룹화 (기존 인덱스의 하위 레벨로 그룹핑) • unstack - 멀티 인덱스를 컬럼 기준으로 재그룹화 시키는 방법 (기존 헤더의 하위 레벨로 그룹핑) _f.stack() I1 C1 1 C2 A I2 C1 2 C2 B dtype: object C1 C2 1 A 2 B I1 I2 C1 C2 인덱스 C1 C2 1 A 2 B I1 I2 인덱스 _f.stack().unstack() Pandas stack과 unstack
  • 118. (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 내용
  • 119. (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
  • 120. (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
  • 121. (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']) # 승인거래, 회귀분석선 출력
  • 122. (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
  • 123. (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']) # 기존 회귀분석, 신규 회귀분석 차트 출력
  • 124. (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 ………
  • 125. (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승인취소 요청
  • 126. (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 시스템장애
  • 127. (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
  • 128. (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
  • 129. (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
  • 130. (2) 전문 거래 로그 분석 전문 처리시간 및 거래 현황 # 초단위로 변경 및 합산을 위한 건수 지정 tf['SEC_GAP'] = tf['TIME_GAP'].dt.seconds tf['COUNT'] = 1 # 처리시간별 현황 tf.groupby('SEC_GAP').sum() # 처리시간 그룹 후 해당 그룹별 합계 (숫자로 지정된 항목인 COUNT만 수행) # 차트 출력 df = tf.groupby('SEC_GAP') df.plot(kind='bar') COUNT SEC_GAP 0 91 1 96 2 112 3 96 4 99 5 106 6 99 7 94 8 104 9 103
  • 131. (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)
  • 132. (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)) # 차트 출력
  • 133. (3) 행정구역별 인구변화 분석 통계청(kosis.kr) 데이터셋 이용 • 통계청 행정구역별 인구 데이터 http://kosis.kr/statHtml/statHtml.do?orgId=101&tblId=DT_1B040A3 • 데이터를 다운 받을 때 '셀병합' 체크를 없앤 뒤 다운로드 • 데이터를 열어보면 아래의 형식이며 파일명은 '행정구역_시군구_별__성별_인구수_2011_2020' 변경 행정구역(시군구)별 2011. 01 2011. 01 2011. 01 2011. 02 2011. 02 2011. 02 2011. 03 2011. 03 행정구역(시군구)별 총인구수 (명) 남자인구수 (명) 여자인구수 (명) 총인구수 (명) 남자인구수 (명) 여자인구수 (명) 총인구수 (명) 남자인구수 (명) 전국 50,534,731 25,318,961 25,215,770 50,555,262 25,328,299 25,226,963 50,575,130 25,337,290 서울특별시 10,312,835 5,110,837 5,201,998 10,314,245 5,110,818 5,203,427 10,307,783 5,107,011 부산광역시 3,566,560 1,772,383 1,794,177 3,566,480 1,772,175 1,794,305 3,564,873 1,770,952 대구광역시 2,512,071 1,255,238 1,256,833 2,512,321 1,255,200 1,257,121 2,511,231 1,254,360 인천광역시 2,761,122 1,391,674 1,369,448 2,765,025 1,393,626 1,371,399 2,768,648 1,395,330 광주광역시 1,456,308 722,450 733,858 1,458,195 723,413 734,782 1,458,326 723,279 대전광역시 1,504,617 754,111 750,506 1,506,136 754,883 751,253 1,506,995 755,385 울산광역시 1,127,337 579,518 547,819 1,127,647 579,732 547,915 1,128,324 580,047 세종특별자치시 - - - - - - - - 경기도 11,801,232 5,949,477 5,851,755 11,815,120 5,956,364 5,858,756 11,829,316 5,963,948 강원도 1,528,790 769,339 759,451 1,527,843 768,790 759,053 1,529,915 769,993 충청북도 1,550,474 781,774 768,700 1,551,621 782,255 769,366 1,552,707 782,832 충청남도 2,076,239 1,049,848 1,026,391 2,077,703 1,050,677 1,027,026 2,081,390 1,052,537 전라북도 1,868,745 931,489 937,256 1,868,363 931,323 937,040 1,868,476 931,437 전라남도 1,916,912 957,989 958,923 1,914,191 956,670 957,521 1,914,176 956,526 경상북도 2,688,586 1,350,687 1,337,899 2,687,178 1,349,953 1,337,225 2,687,521 1,350,106 경상남도 3,291,435 1,656,488 1,634,947 3,291,281 1,656,537 1,634,744 3,293,002 1,657,395 제주특별자치도 571,468 285,659 285,809 571,913 285,883 286,030 572,447 286,152
  • 134. (3) 행정구역별 인구변화 분석 통계청(kosis.kr) 데이터셋 이용 • jupyter notebook을 위한 설정 출력 차트 사이즈를 조정을 위해 figure.figsize 설정 폰트는 맑은고딕 font.sans-serif, font.weight 설정 %matplotlib inline # 차트 웹에서 출력하는 jupyter notebook 매직키워드 import pandas as pd from matplotlib import rcParams rcParams['font.sans-serif'] = 'Malgun Gothic' rcParams['font.weight']='regular' rcParams['figure.figsize'] = 15,10
  • 135. (3) 행정구역별 인구변화 분석 Level 2 멀티컬럼 클린징 방법 #인코딩은 UTF-8, 상단 2개 로우를 헤더로, 첫번째 컬럼을 인덱스로 지정 df = pd.read_csv('행정구역_시군구_별__성별_인구수_2011_2020', header=[0,1], index_col=0) df.head() #멀티 컬럼들에 공백과 '(명)'문자를 제거가 필요 #컬럼을 출력함 for _ in df.columns: print(_) ('2011. 01', '총인구수 (명)') ('2011. 01', '남자인구수 (명)') ('2011. 01', '여자인구수 (명)') ('2011. 02', '총인구수 (명)') ('2011. 02', '남자인구수 (명)') ('2011. 02', '여자인구수 (명)') ('2011. 03', '총인구수 (명)') 행정구역(시군구)별 2011. 01 ... 2020. 04 2020. 05 행정구역(시군구)별 총인구수 (명) 남자인구수 (명) 여자인구수 (명) ... 총인구수 (명) 남자인구수 (명) 여자인구수 (명) 총인구수 (명) 남자인구수 (명) 여자인구수 (명) 전국 50,534,731 25,318,961 25,215,770 ... 51,842,524 25,857,509 25,985,015 51,841,371 25,856,030 25,985,341 서울특별시 10,312,835 5,110,837 5,201,998 ... 9,726,787 4,737,843 4,988,944 9,724,496 4,735,431 4,989,065
  • 136. (3) 행정구역별 인구변화 분석 Level 2 멀티컬럼 클린징 방법 #컬럼들에 존재하는 문자들은 모두 클린징하여 봄 for x in df.columns: print( [_.replace(' ','').replace('(명)','') for _ in x ] ) # df.rename( columns={ '옛이름':'신이름', ... } )에 사용될 딕셔너리 생성 colset = {} for x in df.columns: y = [ _.replace(' ','').replace('(명)','') for _ in x ] colset[x] = tuple(y) colset ['2011.01', '총인구수'] ['2011.01', '남자인구수'] ['2011.01', '여자인구수'] ['2011.02', '총인구수'] ['2011.02', '남자인구수'] ['2011.02', '여자인구수'] {('2011. 01', '총인구수 (명)'): ('2011.01', '총인구수'), ('2011. 01', '남자인구수 (명)'): ('2011.01', '남자인구수'), ('2011. 01', '여자인구수 (명)'): ('2011.01', '여자인구수'), ('2011. 02', '총인구수 (명)'): ('2011.02', '총인구수'), ('2011. 02', '남자인구수 (명)'): ('2011.02', '남자인구수'), ('2011. 02', '여자인구수 (명)'): ('2011.02', '여자인구수'), ..... }
  • 137. (3) 행정구역별 인구변화 분석 Level 2 멀티컬럼 클린징 방법 #컬럼명 변경 df = df.rename(columns=colset) df.head() #데이터프레임의 Level 2의 멀티컬럼을 Level 1로 변경 (튜플 지정) df.columns=df.columns.values (2011. 01, 총인구수 (명)) (2011. 01, 남자인구 수 (명)) (2011. 01, 여자인구 수 (명)) (2011. 02, 총인구수 (명)) (2011. 02, 남자인구 수 (명)) ... (2020. 04, 여자인구 수 (명)) (2020. 05, 총인구수 (명)) (2020. 05, 남자인구 수 (명)) (2020. 05, 여자인구 수 (명)) 전국 50,534,731 25,318,961 25,215,770 50,555,262 25,328,299 25,237,840 25,857,509 25,985,015 51,841,371 25,856,030 서울특별시 10,312,835 5,110,837 5,201,998 10,314,245 5,110,818 5,200,772 4,737,843 4,988,944 9,724,496 4,735,431 (2011.01, 총인구수) (2011.01, 남자인구수) (2011.01, 여자인구수) (2011.02, 총인구수) (2011.02, 남자인구수) ... (2020.04, 여자인구수) (2020.05, 총인구수) (2020.05, 남자인구수) 전국 50,534,731 25,318,961 25,215,770 50,555,262 25,328,299 ... 25,985,015 51,841,371 25,856,030 서울특별시 10,312,835 5,110,837 5,201,998 10,314,245 5,110,818 ... 4,988,944 9,724,496 4,735,431
  • 138. (3) 행정구역별 인구변화 분석 Level 2 멀티컬럼 클린징 방법 #튜플 기준으로 멀티 헤더의 인덱스로 변경함 df.columns=pd.MultiIndex.from_tuples(df.columns) 2011.01 2011.02 ... 2020.04 2020.05 총인구수 남자인구 수 여자인구 수 총인구수 남자인구 수 여자인구 수 ... 총인구수 남자인구 수 여자인구 수 총인구수 남자인구 수 여자인구 수 전국 50,534,7 31 25,318,9 61 25,215,7 70 50,555,2 62 25,328,2 99 25,226,9 63 ... 51,842,5 24 25,857,5 09 25,985,0 15 51,841,3 71 25,856,0 30 25,985,3 41 서울특별시 10,312,8 35 5,110,83 7 5,201,99 8 10,314,2 45 5,110,81 8 5,203,42 7 ... 9,726,78 7 4,737,84 3 4,988,94 4 9,724,49 6 4,735,43 1 4,989,06 5
  • 139. (3) 행정구역별 인구변화 분석 데이터프레임 .T : Trnaspose Index and Columns tf = df.T 2011.01 2011.02 ... 2020.04 2020.05 총인구 수 남자인구수 여자인구수 총인구수 남자인구수 여자인구수 ... 총인구수 남자인구수 여자인구수 총인구수 남자인구수 여자인구수 전국 50,534, 731 25,318,961 25,215,770 50,555,262 25,328,299 25,226,963 ... 51,842,524 25,857,509 25,985,015 51,841,371 25,856,030 25,985,341 서울특별시 10,312, 835 5,110,837 5,201,998 10,314,245 5,110,818 5,203,427 ... 9,726,787 4,737,843 4,988,944 9,724,496 4,735,431 4,989,065 • 시계열 형식으로 변경해야 데이터의 변화를 분석하기 쉬움 • 데이터프레임에는 .T를 통해 인덱스와 컬럼의 위치를 변경할 수 있음 전국 서울특별시 부산광역시 대구광역시 인천광역시 광주광역시 대전광역시 울산광역시 세종특별자 치시 ... 2011.01 총인구수 50,534,731 10,312,835 3,566,560 2,512,071 2,761,122 1,456,308 1,504,617 1,127,337 - ... 남자인구수 25,318,961 5,110,837 1,772,383 1,255,238 1,391,674 722,450 754,111 579,518 - ... 여자인구 수 25,215,77 0 5,201,998 1,794,177 1,256,833 1,369,448 733,858 750,506 547,819 - 5,851,755 ... ... ... ... ... ... ... ... ... ... ... ... df df.T
  • 140. (3) 행정구역별 인구변화 분석 데이터프레임 .unstack : 시계열만 인덱스로 남기고 컬럼을 그룹핑 전국 서울특별시 부산광역시 대구광역시 인천광역시 광주광역시 ... 2011.01 총인구수 50534731 10312835 3566560 2512071 2761122 1456308 ... 남자인구수 25318961 5110837 1772383 1255238 1391674 722450 ... 여자인구수 25215770 5201998 1794177 1256833 1369448 733858 ... 2011.02 총인구수 50555262 10314245 3566480 2512321 2765025 1458195 ... 남자인구수 25328299 5110818 1772175 1255200 1393626 723413 ... 여자인구수 ... ... ... ... ... ... ... # unstack()을 통해 멀티 인덱스 한 개를 컬럼 차원으로 재그룹핑 tf = tf.unstack() 전국 서울특별시 부산광역시 총인구수 남자인구수 여자인구수 총인구수 남자인구수 여자인구수 총인구수 남자인구수 여자인구수 ... 2011.01 50534731 25318961 25215770 10312835 5110837 5201998 3566560 1772383 1794177 ... 2011.02 50555262 25328299 25226963 10314245 5110818 5203427 3566480 1772175 1794305 ... 2011.03 50575130 25337290 25237840 10307783 5107011 5200772 3564873 1770952 1793921 ... 2011.04 50594424 25346019 25248405 10301829 5103919 5197910 3563042 1769903 1793139 ...
  • 141. (3) 행정구역별 인구변화 분석 데이터 시각화 # 인덱스가 X축이 되며, 나머지 값들이 Y축이 되어 출력됨 tf.plot()
  • 142. (3) 행정구역별 인구변화 분석 데이터 시각화 # 서울특별시로 한정하여 출력 tf['서울특별시'].plot()
  • 143. (3) 행정구역별 인구변화 분석 데이터 시각화 # 세종특별자치시로 한정하여 출력 tf['세종특별자치시'].plot()