오늘은 Google Colab. 환경에서 Plotly를 이용해 극좌표 그래프를 그리는 방법에 대해 알아본다.
Plotly를 이용해 극좌표 그래프를 그리는 방법에는 두 가지 정도가 있다.
한가지는 Plotly.express package를 사용하는 방법, 다른 한가지는 plotly.graph_objects 를 이용하는 방법이다.
이름에서도 유추할 수 있듯이, express package를 사용하면 빠르게 그릴 수 있는 대신, 세부적인 옵션은 조절하기 어렵다. 반면 graph_objects는 세세하게 조절할 수 있는 대신 처음부터(?) 그려야한다.
그림에 비유하면 Plotly express는 컬러링 북을 사서 색칠만 하는 느낌이고, Plotly graph_objects는 직접 스케치부터 하는 느낌이다.
무슨말인지 직접 해보면서 알아보자.
먼저 오늘 사용할 Package를 install해주자.
!pip install chart_studio
chart_studio에는 plotly package가 들어있다.
다음 우리가 사용할 package를 불러오자.
import numpy as np
import matplotlib.pyplot as plt
import chart_studio
chart_studio.tools.set_credentials_file(username='username',api_key='api_key')
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
먼저 Plotly express를 이용해 graph를 그려보자. 코드 부터 보면,
a = np.random.rand(36)
df = pd.DataFrame(dict(
r=a,
theta=list(np.arange(0,360,10))
)
)
fig = px.line_polar(df, r='r', theta='theta', line_close=True, )
fig.update_layout(
title = {
'text': 'Sample title',
'y':0.97,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'},
showlegend = True,
)
fig.show()
한줄씩 살펴보자.
a = np.random.rand(36)
먼저 a라는 변수에 np.random.rand 를 이용해 0부터 1사이의 난수 36개를 만들었다.
df = pd.DataFrame(dict(
r=a,
theta=list(np.arange(0,360,10))
)
)
다음, 0부터 350까지 각도를 theta라는 list로 만들고, 각도마다 a라는 값이 대응된 DataFrame을 만들었다.
굳이 DataFrame을 만드나? 싶겠지만, 실제 그래프를 그릴 때 DataFrame을 사용하는 일이 많기 때문에 이런식으로 해 보았다.
df.head()를 통해 어떻게 생겼는지 확인해보면,
요렇게 생겼을 것이다.
이제 데이터가 준비되었으니 그래프를 그려보자.
fig = px.line_polar(df, r='r', theta='theta', line_close=True)
plotly.express를 px로 불러왔는데, px에 있는 line_polar를 이용해서 단 한줄로 (!) 그래프를 완성했다.
괄호안에 들어있는 옵션은 어떤 데이터를 사용할건지, 그리고 r값과 theta값을 그 데이터에서 어떤 column을 이용해서 정해줄건지를 말한다.
line_close의 경우 0도와 350도를 이어주는 역할을 한다. 무슨 말이냐면, 우리가 np.random.rand로 36개, 그리고 theta는 0부터 350도까지 만들었기때문에, 0도와 350사이의 line이 비게 된다. line_close=True로 두게 되면 0도와 350도 사이를 자동으로 연결해준다.
fig.update_layout(
title = {
'text': 'Sample title',
'y':0.97,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'},
showlegend = True,
)
다음은 그래프에 제목을 넣어봤다. showlegend=True로 두었지만 legend를 설정하지 않았기 때문에 legend는 아마 보이지 않을 것이다. 결과물을 보자.
fig.show()
실행시키면
다음과 같은 그래프를 그릴 수 있다.
이제 Plotly.grpah_objects를 이용해서 그려보자. 코드는 다음과 같다.
a = np.random.rand(36)
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=a,
theta=list(np.arange(0,370,10)),
mode='lines',
name='Sample 1')
)
fig.update_layout(
title = {
'text': 'Sample title',
'y':0.97,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'},
showlegend = True,
)
fig.show()
graph_objects를 사용할때는 그릴 도화지를 선언해줘야한다. 그 코드가 바로 이것이다.
fig = go.Figure()
다음, 도화지에 Polar를 그려준다.
fig.add_trace(go.Scatterpolar(
r=a,
theta=list(np.arange(0,370,10)),
mode='lines',
name='Sample 1')
)
mode를 통해 line으로 그릴건지, scatter할건지 등을 결정해 줄 수 있다. 또 이번에는 legend도 설정해주었다.
마찬가지로 title과 legend를 설정해주자.
fig.update_layout(
title = {
'text': 'Sample title',
'y':0.97,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'},
showlegend = True,
)
fig.show()
결과물은 다음과 같다.
우리의 도화지 fig.에 add_trace를 더해서 여러개를 그릴 수도 있겠다.
a=np.random.rand(37)
b=np.random.rand(37)
c=np.random.rand(37)
fig = go.Figure()
fig.add_trace(go.Scatterpolar(
r=a,
theta=list(np.arange(0,370,10)),
mode='lines',
name='Sample 1')
)
fig.add_trace(go.Scatterpolar(
r=b,
theta=list(np.arange(0,370,10)),
mode='markers',
name='Sample 2')
)
fig.add_trace(go.Scatterpolar(
r=c,
theta=list(np.arange(0,370,10)),
mode='lines+markers',
name='Sample 3')
)
fig.update_layout(
title = {
'text': 'Sample title',
'y':0.97,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'},
showlegend = True,
)
fig.to_show()
이외에도 graph의 선 두께, 색상, 형태, opacity, size 등 굉장히 세세하게 - 생각할 수 있는 거의 모든 옵션을 건드릴 수 있다. 자세한 내용은 공식문서를 참고하는 것이 좋겠다.
plotly.github.io/plotly.py-docs/generated/plotly.graph_objects.Scatterpolar.html
마지막으로 이를 이용한 예시 그래프를 하나 남기고 이만 글을 마쳐보겠다.
위의 그래프는 다음과 같은 fig.updat_layout을 이용해 업데이트 해주었다. polar의 옵션들을 dict로 넣어주면 된다.
radialaxis의 font, angularaxis의 font, rotation, direction(시계or반시계) 등을 정해줄 수 있다.
fig.update_layout(
title ={
'text': 'HWP의 Fast axis각도 별 빛의 세기 분포',
'y':0.97,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'},
showlegend = True,
polar = dict(
radialaxis_tickfont_size = 8,
angularaxis = dict(
tickfont_size=8,
rotation=90, # start position of angular axis
direction="clockwise")
)
)