블로그 이미지
자유로운설탕

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2017. 5. 21. 15:38 프로그래밍

  이번 시간은 지난 시간에 이어 수학 라이브러리의 일환인 그래픽(정확하게는 plotting 이겠지만..) 라이브러리를 살펴보려고 한다. 지난 시간에 언급되었던, matplotlib 과 Plotly 로 예제를 구현해 보면서, 어떻게 사용에 접근하면 좋은지에 대해 얘기해 보려고 한다.

 

 

[목차]

0. 왜 파이썬 공부에 구글을 이용하는게 좋은가?

1. 언어를 바라보는 방법. 파이썬을 어떻게 바라봐야 할까?

2. 파이썬 설치와 환경, 버전 선택 하기의 이유.

3. 만들고자 하는 기능을 모르는 조각으로 나눠 조사해 보기

4. 데이터 베이스에서 내용 가져와 출력하기

5. 암호화 모듈을 이용해 암복호화 해보기

6. 퍼즐 조각들을 합쳐보기

7. 엑셀 파일 사용해 보기 -> 부록 : fuction 을 이용해서, 코드 정리해 보기

8. 정규표현식을 왜 사용해야 할까? 언어속의 미니 언어 정규표현식 살펴보기

9. 입력과 결과를 GUI 화면과 연결해 보기

10. Whois API 이용해 보기

11. 웹페이지 호출해 내용 파싱 하기(BeautifulSoup 그리고 한계)

12. 자동화 - 웹 자동화(with Selenium)

13. 자동화 - 윈도우즈 GUI 자동화(with pywinauto)

14. 자동화 - 작업 자동화

15. 수학 라이브러리 살펴보기

16. 그래픽 라이브러리 살펴보기

17. 머신러닝에서의 파이썬의 역활

18. 웹 프로그래밍 - Legacy Web

19. 웹 프로그래밍 - Flask 살펴보기(feat. d3.js)

20. 웹 프로그래밍 - Django 살펴보기

21. 정리 - 이런저런 이야기

 

 

 

[들어가면서]

  우선 예제를 구현해 보기전에 플로팅(plotting) 이라는게 뭔지 잠깐 생각해 보자. plot 이란 특정한 데이터 셋을 공간상에 표시해 주는 것을 이야기 한다. 굳이 2D 평면이 아닌 공간이라고 얘기해도 되는건, 미래에 홀로그램 형태의 3차원 형태의 디스플레이 같은 것이 일반화 된다면 아마 공간 상에 뿌려서 살펴 보는 것도 가능할 것 같아서이다(3D 프린터 같이 말이다). 뭐 여튼 현재 라이브러리는 2차원 화면상에 3차원 좌표까지 표시가 가능하긴 하지만, 아래와 같이 하나의 차원을 색으로 치환해, 평면상에 4차원의 데이터를 표시하는 것도 가능하다(뭐 공간적인 4차원이 아니라고 가짜라고 볼 수도 있겠지만, 어차피 plot 의 목적은 공간에 요소를 단순히 나타낸다기 보다는 각 구성 요소들의 독립, 복합적 관계를 파악하기 위한 목적이 크기 때문에(그 날의 매출 현황이라든지, 이상 이벤트 발생이라든지), 그래프 상에 사람이 차이를 식별할 수 있는 색이나, 점의 모양, 기울기 등도 하나의 인식가능한 차원의 그래프 요소라고 할 수 있을 것 같다.

http://engi-agora.tistory.com/37

 

  우리는 이렇게 좌표 형태로 그려진 그래프를 봄으로써 데이터의 추이, 이상현상, 군집, 분포, 차이 등의 특성에 대해 일련의 데이터 숫자 값들을 직접 보는 것보다 시각적으로 쉽게 파악할 수 있게 된다(물론 의미 있는 데이터를 잘 선택해 적절한 기법으로 뿌려줬을 때의 얘기긴 하지만 말이다). 어느정도 플로팅은 통계나 추이와 같은 감각들을 인간에게 시각적으로 전달해 주는 수학적 도구라고 볼 수 있을 것 같다.

 

 

  개인적으로 이 글을 쓰기 위해서 이런 저런 책과 웹페이지들을 참고해 보면서, 인상 깊었던 2개의 그래프는, 복소수의 곱을 좌표상에 표시해 준 것과, 산포도 이다. 첫번째 복소수의 곱을 좌표상에 표시한 부분은 아래의 페이지에 나온 것 같이 두 복소수를 곱했을 때의 의미가 공간 적으로는 아래와 같이 두 개의 좌표상의 각을 더한 회전으로 나타내게 된다는 것을 이야기 한다.  

[출처 : https://www2.clarku.edu/~djoyce/complex/mult.html ]

 

  두 번째 산포도는 특정한 두 요소가 서로 얼마나 상관이 있느냐 하는 것을 보여 주는 것이다. 예를 들어(통계는 잘 몰라서 예가 적절한진 모르겠지만 --;) 치킨을 100만큼 좋아하는 사람이 맥주를 얼마나 좋아하고, 치킨을 10만큼 좋아하는 사람이 맥주를 얼마나 좋아하는지를 각각 좌표안에 찍는다면, 아래의 그래프와 같이, 오른쪽으로 상승하는 좁은 타원 형태의 그래프 분포를 보인다면, 두 요소는 상관 관계를 가지고 있을 가능성이 존재한다고 합리적 의심을 가져볼 수 있다.

 

  그러면 한번 앞에 언급했던 2개의 많이 쓰이는 그래픽 라이브러리(matplotlib, plotly)를 이용해서, 복소수의 곱과, 산포도를 그려보는 예제를 만들어 보도록 해보자. 앞 시간에 살펴봤던 numpy 를 이용해 데이터를 생성하거나 담는 그릇으로 사용할 것이고, 해당 그릇을 그래프를 그리는 라이브러리에 전달하려고 한다.

 

 

 

 

 

[Matplotlib 을 이용한 복소수의 곱 과정을 그래프로 표시하기]

   뭐 저도 수학은 정말 잘 못해서, 복소수에 대해서 잘 모르기에, 이 예제를 만들기 위해서 책도 좀 읽고, 이것저것 급조를 좀 해봤다. 지나가는 수학과 분이 계시면 그냥 살포시 지나가시기를...

 

 

  위의 방정식의 해를 풀기 위해서는 x의 제곱이 -1 이 되어야 한다. 즉 아래와 같이 x가 루트 -1 이 되어야 하는데, 이 실수 관점에서 보면 혈통을 인정하기 힘든 가상의 수(루트 -1)를 i (복소수)라고 그런다. 그래서 i 의 제곱은 -1 이 된다.

 

그럼 그래프로 그려볼 간단한 곱을 하나 해보자. A 를 0.5+1i, B 를 1+0.5i 라고 하면,

(0.5+1i)*(1+0.5i) = 0.5*1 + 0.5*0.5i + 1i*1 + 1i*0.5i = 0.5 + 0.25i + 1i + 0.5i^2

= 0.5 + 0.25i + 1i + 0.5*(-1) = 1.25i 

 

  음 수식 상으로는 실수 부가 사라지고, 허수부만 '1.25i' 로 남게 된다.(고백하자면 일부러 각도가 합해지는게 잘 인지되는 그림을 그리기 위해서 복소수를 정할때, B는 x축 기준으로 30도, A는 60도 가 되게 만들어서, 두 개를 곱하면 직각인 90도가 되게 만들었다).

 

 

 

  이제 파이썬으로 그래프를 그려 보려 한다. 일단 첫번째로 막히는게, 파이썬에선 복소수를 어떻게 다루지? 하는 부분이다. 어떤 라이브러리를 써야 되는지도 모르겠고, 어떤 문법을 가졌는지도 모르겠다. 구글에다 우선 'python complex number' 라고 검색해 보자.

https://stackoverflow.com/questions/8370637/complex-numbers-usage-in-python

 

  위의 페이지를 보니, 생각보다 휠씬 간단해 보인다. 복소수를 쓰기 위해 complex 란 함수를 이용해도 되지만, 그냥 1 + 2j (파이썬은 i가 아니라 j임, 위키를 보면 전류를 나타내주는 기호 i와 구분하기 위해서 공학 쪽에서 j라고 쓴다고 하는 설이...) 라고 써주면 파이썬이 알아서 인식해 주나보다. 그럼 샘플을 참고하여 해당 방식으로 두 개의 복소수를 곱해서 결과를 화면에 나타내는 코드를 만들어 보자.

1
2
3
4
5
6
#-*- coding: utf-8 -*-
 
= 0.5+1j
= 1+0.5j
= a*b
print(c)
cs

 

  위의 파일을 c:\python\code 폴더에 utf-8 인코딩으로, complextnum.py 라고 저장한다(역시 이 부분을 잘 모르겠으면 2교시에서 복습을!). 이후 아래와 같이 실행해 본다.

c:\Python\code>python complextnum.py
1.25j

 

 

  아까 손으로 열심히 계산한, '1.25j' 결과가 나온다. 그럼 이제 그래프를 그려보기 위해서 일단 matplotlib 을 설치한다.

c:\Python\code>pip install matplotlib
Collecting matplotlib
  Downloading matplotlib-2.0.2-cp35-cp35m-win_amd64.whl (8.9MB)
..
Successfully installed cycler-0.10.0 matplotlib-2.0.2 pyparsing-2.2.0

 

 

  이후 구글에서 'complex number python plot' 라고 검색해서 아래의 스택오버플로우 페이지를 찾았다.

https://stackoverflow.com/questions/17445720/how-to-plot-complex-numbers-argand-diagram-using-matplotlib

 

  제일 밑에 보면, 복소수를 좀 더 잘 나타내는거 같은 극좌표 형식의 그래프도 있는 것 같지만, 좀 더 상황을 간단히 하기위해서(현재 그래프를 그려보는 시간이지, 복소수를 공부하는 시간은 아니므로...), 일반 평면 좌표계를 사용하려 한다.

 

  개인적으로 그리기 전에 원하던 그래프의 모양은 아래와 같았다.

  • 화면에 점만 찍는게 아니라 원점으로 부터 점까지 선이 연결되길 바랬다(그게 좀더 점들의 각도를 잘 보여줄 것 같아서)
  • 그래프의 비율이 실제 좌표와 동일하게 1:1 이길 바랬다. 비율이 다르다면 각도가 왜곡 되어 보일 수 있기 때문에 말이다
  • 각 선은 서로 다른 색으로 표시됬음 했고, 가로-세로 축 선을 표시하고, 그리드도 표시되었음 했다.

 

   여기 까지 계속 읽어 오신 분들은 이제 저랑 함께 초보 수준은 살짝 벗어났다고 생각해서, 읽는 지루함을 없애기 위해서 예전 시간들 처럼 모든 시행 착오를 다 보여주진 않고, 각각의 요소를 해결한 방법들을 간단히 명시후에, 최종 코드를 제시해 보이려고 한다^^

 

 

  먼저 위의 스택 오버플로우 코드를 참고해서 그래프를 그려 보니, 가로축과 세로축의 비율이 일정치 않아 각도가 정확하게 보이지 않았다. 그래서 구글에 '
matplotlib aspect ratio'  로 검색해 아래의 페이지의 코드를 찾았다.

https://matplotlib.org/examples/pylab_examples/equal_aspect_ratio.html

1
plt.axes().set_aspect('equal''datalim')
cs

 

 

  가로, 세로 축을 보이게 하는 코드는 'matplotlib show x y axis' 로 찾아 아래와 같다.

1
2
ax.axhline(y=0, color='k')
ax.axvline(x=0, color='k')
cs

 

 

  그리고 각각의 선의 색을 다르게 표시하기 위해 구글에 'matplotlib plot change color' 라고 검색해서 아래의 페이지에서 관련 코드를 찾았다. 여기서는 그래프에 화살표와 함께 주석을 다는 코드도 있어서 해당 코드를 이용해서 해당 되는 복소수의 선들에 이름표를 달기로 했다.

https://matplotlib.org/users/pyplot_tutorial.html

1
2
3
4
5
6
7
8
# c 가 색을 나타냄
Here are the available Line2D properties.
color or c : any matplotlib color 
 
# 그래프 안에 주석 
plt.annotate('local max', xy=(21), xytext=(31.5),
            arrowprops=dict(facecolor='black', shrink=0.05),
            )
cs

 

 

  참고로 그래프 내의 title 등에 한글 표시를 원하는 분들은 아래의 블로그 같은데에 해결 방법이 있지만('matplotlib 한글 깨짐' 같은 걸로 찾아서), 적용 해보니까 폰트에 따라서 숫자의 '-' 표시가 안 나온다든지 하는 여러가지 사소하게 귀찮은 일들이 생겨서 글의 논점을 흐릴 듯 해서 그냥 전 영문으로 진행했다.

http://pinkwink.kr/956

 

 

  그래서 우여곡절 끝에 완성된 최종 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#-*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
 
# 수식 정의
= 0.5+1j
= 1+0.5j
= a*b
 
# numpy 에 복소수들 담기
arr = np.array([a, b, c])
 
# 여기서 i 는 색 루프를 돌리기 위해서..
= 0
for x in arr:
   # 칼라 지정용 배열
   arrColor = np.array(['yellow','brown','magenta'])
   # 지정된 색으로 해당 복소수의 실수부(real), 허수부(iamg)를 그림.
   plt.plot([0,x.real],[0,x.imag],'ro-',c=arrColor[i])
   i = i + 1
 
# 그래프 제목
plt.title('Complex Number Multiplication')
# 그리드 보이기
plt.grid(True)
# 가로세로 1:1 비율 만들기
plt.axes().set_aspect('equal''datalim')
# x,y 축 이름 짓기
plt.ylabel('Imaginary')
plt.xlabel('Real')
# 그래프가 보이는 최대 최소 범위 지정
plt.xlim((-2,2))
plt.ylim((-2,2))
# x, y 축 보이기
plt.axhline(y=0, color='k')
plt.axvline(x=0, color='k')
 
# 주석 달기       
plt.annotate('0.5+1i (a)', xy=(0.51), xytext=(0.70.8),
            arrowprops=dict(facecolor='black', shrink=0.01),
            )
 
plt.annotate('1+0.5i (b)', xy=(10.5), xytext=(1.20.3),
            arrowprops=dict(facecolor='black', shrink=0.01),
            )
            
plt.annotate('(1+0.5i)*(0.5+1i) (c=a*b)', xy=(01.25), xytext=(0.21.1),
            arrowprops=dict(facecolor='black', shrink=0.01),
            )           
 
# 그린 그래프 보여주기
plt.show()
cs

 

 

  저장 후 실행하면 아래와 같이 그래프가 보이게 된다. 두 개의 복소수가 곱해져서, 길이는 1.25 가 되고(1.25i), 각도는 x축 기준으로 30도(b), 60도(a)가 합해져 90도(c)가 된 모습을 기하학적으로 확인 할수 있다(개인적으로는 이렇게 대수학이 기하학으로 표시되어 직관적으로 이해되는 부분이 재밌는거 같다~).

c:\Python\code>python complextnum.py

 

 

 

 

 

 

[Plotly 을 이용해 산포도 그리기]

   먼저 진행 하기 앞서서 결론적인 하나의 부분만 얘기하면, plotly 는 matplotlib 처럼 완전 무료는 아니고(커뮤니티 라이센스는 있어 그래프 종류에 따라 무료로 하루에 50~250개의 그래프는 그려볼 수 있다-> 보충 부분에 링크를 걸어놓았지만, Offline 모드로 실행을 할 수 있다. 일단 온라인 모드에만 해당하는 이야기로 정정한다.), 파이썬에서 해당 사이트로 데이터를 보내서, 사이트 내의 계정에 데이터와 그래프를 저장하는 방식같다. 클라우드 그래프 라이브러리라고 보면 될듯 하다. 다만 그래프는 상용이라 그런지 조금 더 기본 디자인이 깔끔해 보이고 이런 저런 export 등 도 가능해 보인다(예제에는 ipython notebook 에 삽입 가능하다고 되어 있는데, 명령어로 실행하는 입장이라서 잘 모르겠다..). 가격별 차이의 상세한 부분은 아래 링크를 참조한다.

https://plot.ly/products/cloud/ 

 

  먼저 plotly 라이브러리를 설치한다.

c:\Python\code>pip install plotly
Collecting plotly
....
Successfully installed decorator-4.0.11 ipython-genutils-0.2.0 jsonschema-2.6.0 jupyter-core-4.3.0 nbformat-4.3.0 plotly-2.0.8 traitlets-4.3.2

 

 

  산포도를 그리는 방법을 찾기 위해 구글에서 'scattergram plotly' 라고 검색하여 아래의 샘플 페이지를 찾는다.

https://plot.ly/python/line-and-scatter/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#-*- coding: utf-8 -*-
import plotly 
import plotly.plotly as py
import plotly.graph_objs as go
import numpy as np
 
# 랜덤 값 만들기
= 1000
random_x = np.random.randn(N)
random_y = np.random.randn(N)
 
# 트레이스 만들기
trace = go.Scatter(
    x = random_x,
    y = random_y,
    mode = 'markers'
)
 
data = [trace]
 
# 그리기
py.iplot(data, filename='basic-scatter')
cs

 

 위의 파일을 c:\python\code 폴더에 utf-8 인코딩으로, plotlytest.py 라고 저장한다. 이후 아래와 같이 실행해 본다(...)

c:\Python\code>python plotlytest.py

KeyError: 'plotly_domain'

 

  실행하면 위와 같은 에러가 발생한다. 구글에 'KeyError: 'plotly_domain''로 찾아서 확인해 보면 iplot 대신 plot 을 사용하라고 한다. 아래 해당 부분 코드만 수정해 다시 돌려본다. (편집 환경으로 ipython 을 사용하시는 분들은 에러가 안 날수도 있을 것 같다)

https://stackoverflow.com/questions/34929778/keyerror-plotly-domain-when-using-plotly-to-do-scatter-plot-in-python

1
py.plot(data, filename='basic-scatter')
cs

 

c:\Python\code>python plotlytest.py

Aw, snap! We don't have an account for ''. Want to try again? You can authenticate with your email address or username. Sign in is not case sensitive.
Don't have an account? plot.ly
Questions?
support@plot.ly

 

그런데 이번엔 계정이 없다고 얘기한다(첨에 나온 라이센스 관련 페이지가 이걸 만나서 찾아보다가 가게된 것이다. 그래서 사실 완전 무료가 아닌 이 라이브러리를 소개해야 되나마나 조금 고민하긴 했다). 다시 구글에 'Don't have an account? plot.ly' 라고 검색하여 아래의 안내 페이지를 찾는다.

https://plot.ly/python/getting-started/

 

 

결국 plotly 라이브러리를 사용하기 위해서는 아래 네 가지를 해야한다.

  • 회원 가입
  • API 키 발급(kisa api 를 사용할 때와 비슷하다)
  • 이메일 인증(API키만 발급 하고 해보니, 안되서 이메일 인증도 했다)
  • python 코드안에 계정 정보 넣기. (어떤 원리로 캐싱이 되는진 모르지만 한번 넣고 실행 후엔 해당 계정 정보는 코드에서 빼도 해당 계정으로 실행이 되긴 한다)

 

  그럼 회원 가입 페이지로 가서 회원 가입을 한다. (이메일, 계정 이름, 패스워드)

https://plot.ly/accounts/login/?next=%2Fsettings%2Fapi

 

 

  이후 로그인 한 상태에서 아래 페이지로 가서 API 키를 '재생성' 시킨다. 이후 해당 키를 적당히 메모장 등에 저장해 둔다.

https://plot.ly/settings/api

 

 

  자신의 메일로 가면 plotly 에서 보낸 인증 메일이 와 있을 것이다. 인증 링크를 클릭한다.

 

 

  이후 코드를 최종 수정하여, 아래와 같이 API 키 정보를 집어 넣는다. (whois API 때와 마찬가지로 코드내의 '본인계정', '본인API키' 항목 부분은 각자 발급한 키로 수정해 주어야 동작한다)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#-*- coding: utf-8 -*-
import plotly 
import plotly.plotly as py
import plotly.graph_objs as go
import numpy as np
 
# API 키 정보 넣기
plotly.tools.set_credentials_file(username='본인계정', api_key='본인API키')
 
# 랜덤 값 만들기
= 1000
random_x = np.random.randn(N)
random_y = np.random.randn(N)
 
# 트레이스 만들기
trace = go.Scatter(
    x = random_x,
    y = random_y,
    mode = 'markers'
)
 
data = [trace]
 
# 그리기
py.plot(data, filename='basic-scatter')
cs

 

  다시 저장해 실행해 본다.

c:\Python\code>python plotlytest.py

High five! You successfuly sent some data to your account on plotly. View your plot in your browser at https://plot.ly/~계정이름/0 or inside your plot.ly account where it is named 'basic-scatter'

 

 

  실행이 잘 됬다고 나오면서, 브라우저 창에 https://plot.ly/~본인아이디/0/ url이 뜨면서, 로그인 창이 나온다. 로그인 탭을 눌러 아까 발급 받은 계정으로 로그인 한다.

 

 

  로그인이 되면 아래와 같이 그리려던 그래프가 웹 화면에 보이게 된다. 상단의 'export' 메뉴를 클릭하면 그래프를 이미지 파일로 저장하거나, 데이터를 문서로 만들거나, 다른 언어로(매트랩, R 등) 코드를 내보낼 수도 있다.

 

 

 

 

[마무리 하면서]

  설명은 엄청 장황했지만, 결론은 엄청 간단하다. 그래픽 라이브러리를 쓰는 방법은 아주 단순하다. 데이터들을 잘 모아서 numpy 배열 같은데에 담는다. 이후 plot 해 주는 라이브러리에 해당 배열을 전달해 주면 된다. 그리고 적당히 원하는데로 좌표 공간을 꾸미면 된다. 하지만 이 간단함에 숨어있는 어려움이 올바른 데이터를 수집하고, 그 수집한 데이터의 품질이 충분히 현실과 견주어 의미가 있어야 하고, 해당 특징을 잘 해석해 나타내 줄 적절한 그래프 함수를 선택하는 눈을 키우는 부분이다. 이것은 아마 다음 시간에 다룰 머신러닝에서의 파이썬 측면에서도 비슷한 문제가 될 것 같다.

 

 

 

[보충]

  검색을 하다보니 plotly 를 offline 모드로 하는 예제를 보았다. 이렇게 하면 위와 같은 인증 절차도 필요 없어 지는듯 싶다. (어쩐지 온라인 모드만 되는 툴이 저렇게 인기가 많나 했다;)

http://hamait.tistory.com/800

 

  plot 공식 사이트 쪽 설명은 아래에, 특별한 기능차이가 없다면 오프라인을 쓰는게 더 편할 듯 싶다. 온라인과 오프라인이 차이가 있는지는 명확하게 설명된 내용은 없는것 같다.

https://plot.ly/python/getting-started/

https://plot.ly/python/offline/

 

 

 

 

2017.5.28 by 자유로운설탕
cs

 

 

posted by 자유로운설탕