Python matplotlib : xscale, yscale, set_xscale, set_yscale (x축 scale 조절, y축 scale 조절, log scale, subplot log scale)
데이터 분석을 하다보면 시각화는 꽤 중요한 부분 중 하나입니다.
근데 간혹 x축 값과 y축 값이 너무 커지게 되면 값들을 좌표평면 상에 나타낸다고 해도 그 경향성을 시각화하기가 어려울 수 있습니다.
예를들어 y = 1500 / x 라는 함수를 만족하는 값들을 가지고 있고, 이 값들을 그래프로 나타내본다고 해봅시다.
import matplotlib.pyplot as plt
import numpy as np
list_x = np.linspace(0, 2000, 10000)
list_y = []
for x in list_x:
val_result = 1500 / x
list_y.append(val_result)
plt.plot(list_x, list_y,
color='gray')
plt.show()
matplotlib를 이용해 y = 1500 / x 그래프를 x = 0 ~ 2000 구간에서 그리면 위와 같습니다.
위 그래프는 올바른 그래프입니다. 또한 우리는 이미 유리함수가 어떻게 생겼는지 알고 있기 때문에 굳이 그래프를 그리지 않아도 y = 1500 / x가 어떤 모양일지 짐작은 가죠.
근데 위 그래프를 보면 별로 시각화라는 의미와는 좀 다른 것 같습니다.
왜냐면 x축 범위가 너무 넓고 그에 따른 y값 또한 너무 커서 정말 너무 큰 규모의 경향성만 보일 뿐 좀 더 작은 단위의 경향성은 보이지 않습니다.
이것은 매우 당연한 현상입니다.
x값의 범위가 0~2000이며, y = 1500 / x 함수에서 x가 0에 가까운 값일수록 y값은 거의 무한대로 커지니까요.
또한 x값이 커지면 커질수록 y = 1500 / x 함수의 y값도 0에 수렴하므로 그 차이가 매우 적어질겁니다.
즉, 위처럼 그래프가 그려지는 것은 정상이라는거죠.
뭔가 위 이미지처럼 흔히 알고 있는 곡선의 곡률이라던지 이런 변화를 좀 더 눈에 띄게 보고싶은데 그럴 수가 없죠.
위 그래프에서 x축의 값을 좀 더 압축할 수 있으면, 즉, x축 눈금 사이의 간격을 똑같은 간격이 아니라 더 압축시켜서 나타낼 수 있으면 뭔가 그 경향성이 더 잘 나타날 수 있을 것 같습니다.
이럴 때 사용할 수 있는 유용한 설정이 바로 xscale, yscale입니다.
아래 예시를 보시죠.
import matplotlib.pyplot as plt
import numpy as np
list_x = np.linspace(0, 2000, 10000)
list_y = []
for x in list_x:
val_result = 1500 / x
list_y.append(val_result)
plt.plot(list_x, list_y,
color='gray')
plt.xscale('log')
plt.show()
plt.xscale('log')라는 부분을 추가했습니다.
이것은 x축의 scale을 log scale로 나타내겠다는 의미입니다.
그리고 그 결과를 봅시다.
보면 아까보다 그래프의 곡률이 훨씬 더 잘 보이는 그래프가 되었습니다.
그리고 x축에는 큰 눈금이 총 4개가 있고 각각 1, 10, 100, 1000이 되었습니다.
x축을 log scale로 설정했기 때문입니다.
이전 그래프를 보면 x축눈금 하나마다 0, 250, 500, ... 등으로 x축 값이 선형으로 증가하는 것을 볼 수 있습니다.
이것이 기본적인 그래프이며 보통 저희가 다룰 때 이렇게 하죠.
그러나 위 그래프를 보면 x축에 총 4개의 큰 눈금이 있고 그 값은 각각
1
10
100
1000
입니다.
log scale의 의미가 여기서 나오는데 위 x눈금 값에 log를 씌우면 아래와 같습니다.
0 = log1
1 = log10
2 = log100
3 = log1000
즉, log scale이란 각 x축 눈금의 값에 log를 씌우면 0, 1, 2, 3 같은 선형 log값이 되도록 나타내는 방식입니다.
물론 실제 의미하는 값은 log를 씌우기 전인 1, 10, 100, 1000이 되는것이구요.
이렇게되면 그래프 상에서 1, 10, 100, 1000 각각의 x축 눈금의 간격은 동일하게 보이더라도
실제 그 값의 차이는 점점 커지므로 x축의 값들이 마치 압축되어서 보이는 효과가 있습니다.
(1 -> 10은 9 차이이지만 100 -> 1000 차이는 900이죠. 따라서 100 ~ 1000 구간에는 그래프 상에서 동일한 간격 안에 훨씬 더 많은 x축 값들이 압축되어있다고 보시면 됩니다.)
그니까 x값이 늘어날수록 x축 값이 압축되면서 그래프가 좌우로 늘어나는 것처럼 보이는 것이죠.
이를 이용해 우리는 그래프의 경향성을 더 잘 볼 수 있게 되는 것이구요.
xcale 말고 yscale도 존재합니다.
import matplotlib.pyplot as plt
import numpy as np
list_x = np.linspace(0, 2000, 10000)
list_y = []
for x in list_x:
val_result = 1500 / x
list_y.append(val_result)
plt.plot(list_x, list_y,
color='gray')
plt.yscale('log')
plt.show()
yscale('log')로 지정하면 y축도 log scale로 나타낼 수 있습니다.
마찬가지로 원래 그래프보다 경향성이 잘 나타나는 것을 볼 수 있죠.
이렇듯 필요에 따라 xscale, yscale 중 어떤 것을 어떤 방식으로 지정할지 결정하면 됩니다.
scale 지정할 때 사용할 수 있는 키워드는 대표적으로 아래와 같습니다.
linear -> 우리가 기본적으로 사용하는 선형 scale입니다. matplotlib의 기본값입니다.
log -> log scale로 나타내줍니다. 다만 일반적인 log scale이기 때문에 양수만을 나타내주게 됩니다. (0 ~ +logX)
symlog -> 원점을 중심으로 음수, 양수가 대칭인 log scale을 나타내줍니다. (-logX ~ +logX)
logit -> 0~1 사이의 범위를 log scale로 나타내줍니다.
log scale은 subplot에도 적용할 수 있습니다.
다만 코드가 살짝 다릅니다.
import matplotlib.pyplot as plt
import numpy as np
list_x = np.linspace(0.1, 1000, 10000)
list_y = 1600 / list_x
fig, graph = plt.subplots(2, 2)
graph[0][0].plot(list_x, list_y)
graph[0][1].plot(list_x, list_y)
graph[0][1].set_xscale('log')
graph[1][0].plot(list_x, list_y)
graph[1][0].set_yscale('log')
graph[1][1].plot(list_x, list_y)
graph[1][1].set_xscale('log')
graph[1][1].set_yscale('log')
plt.show()
위 코드의 결과는 다음과 같습니다.
총 4개의 그래프가 있으며
왼쪽 위 그래프 = 원본 그래프
오른쪽 위 그래프 = x축만 log scale
왼쪽 아래 그래프 = y축만 log scale
오른쪽 아래 그래프 = x축, y축 모두 log scale
로 나타낸 것입니다.
import matplotlib.pyplot as plt
import numpy as np
list_x = np.linspace(-1000, 1000, 100000)
list_y = []
for x in list_x:
val_result = 1500 / x
list_y.append(val_result)
plt.plot(list_x, list_y,
color='gray')
plt.xscale('linear')
plt.show()
y = 1500 / x 그래프를 그려보았습니다.
그래프가 마치 + 처럼 생겼지만 x축 스케일과 y값이 너무 커서 저렇게 보이는 것입니다.
import matplotlib.pyplot as plt
import numpy as np
list_x = np.linspace(-1000, 1000, 100000)
list_y = []
for x in list_x:
val_result = 1500 / x
list_y.append(val_result)
plt.plot(list_x, list_y,
color='gray')
plt.xscale('symlog')
plt.show()
y = 1500 / x 그래프를 xscale = symlog로 설정했을 때의 그래프입니다.
우리가 흔히 보는 유리함수의 모습이 나타난 것을 볼 수 있습니다.
scale을 symlog로 설정했더니 -1000, -100, -10, -1의 음수 영역까지 나오는 것을 볼 수 있습니다.
import matplotlib.pyplot as plt
import numpy as np
list_x = np.linspace(-1000, 1000, 100000)
list_y = []
for x in list_x:
val_result = x ** 3
list_y.append(val_result)
plt.plot(list_x, list_y,
color='gray')
plt.xscale('log')
plt.show()
이번엔 y = x ^ 3 그래프입니다.
그래프가 x > 0인 부분에 대해서만 나타내지는 것을 볼 수 있습니다.
xscale = log로 지정했기 때문에 x가 양수인 부분만 log scale로 나타내어진 것입니다.
import matplotlib.pyplot as plt
import numpy as np
list_x = np.linspace(-1000, 1000, 100000)
list_y = []
for x in list_x:
val_result = x ** 3
list_y.append(val_result)
plt.plot(list_x, list_y,
color='gray')
plt.xscale('symlog')
plt.show()
이번에는 xscale = symlog로 설정한 결과입니다.
x축 값이 0을 기준으로 음수값, 양수값이 모두 나타내어져 y = x ^ 3 그래프가 그려진 것을 알 수 있습니다.
- 참고
https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.xscale.html