こんにちは、エンジニアのオオカベです。
グラフの背景を画像にしたいと思ったことはありませんか?
私はあります。
例えば画像の閲覧数のデータがあるとして、 上の図のように閲覧数の推移と実際の画像が一目で分かると便利じゃないでしょうか?

というわけで今回はmatplotlibとPILを使用して、グラフの背景に画像を埋め込んで行きます。

画像の埋め込み方

画像の埋め込みはとても簡単で、PILのImage.openで読み込んだイメージをmatplotlibのax.imshowに渡すだけです。

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

fig = plt.figure(figsize=(8, 6))
fig.patch.set_facecolor('white')
ax = fig.add_subplot(1, 1, 1)

im = Image.open("images/cat.jpg")
ax.imshow(im, alpha=0.6)
plt.show()

グラフを重ねる

この背景に対して以下のようなサイン波のグラフを描きたいとします。

fig = plt.figure(figsize=(8, 6))
fig.patch.set_facecolor('white')
ax = fig.add_subplot(1, 1, 1)

x = np.arange(0, 100, 0.01)
y = np.sin(0.02 * np.pi * x) * 100
ax.plot(x, y, color="black")
plt.show()

matplotlibはplt.show()する前に描いた図を全て重ねて表示してくれます。 よってこの場合は

  1. 背景を描く
  2. グラフを描く
  3. plt.show()
とすれば、背景にグラフを重ねて表示してくれるはずです。

しかし素直に重ねてみた場合、以下のように失敗します。
画像のスケールとグラフのスケールが合っていないため、グラフが途切れてしまいました。

fig = plt.figure(figsize=(8, 6))
fig.patch.set_facecolor('white')
ax = fig.add_subplot(1, 1, 1)

x = np.arange(0, 100, 0.01)
y = np.sin(0.02 * np.pi * x) * 100
ax.plot(x, y, color="black")

im = Image.open("images/cat.jpg")
ax.imshow(im, alpha=0.6)
plt.show()

画像をグラフにフィットさせる

ax.imshowの際に引数extentで画像を伸び縮みさせる必要があります。
get_xlim(), get_ylim()でもらってきたグラフのスケールをextentにわたしましょう。
この際、画像が大きく崩れてしまうのであればaspect='auto'としましょう。  

fig = plt.figure(figsize=(8, 6))
fig.patch.set_facecolor('white')
ax = fig.add_subplot(1, 1, 1)

x = np.arange(0, 100, 0.01)
y = np.sin(0.02 * np.pi * x) * 100
ax.plot(x, y, color="black")

xlim = ax.get_xlim()
ylim = ax.get_ylim()

im = Image.open("images/cat.jpg")
ax.imshow(im, extent=[*xlim, *ylim], aspect='auto', alpha=0.6)
plt.show()

終わりに

弊社ではデータスクレイピングだけでなく、pythonを用いた機械学習やデータビジュアライズなども承っております。
最近流行りのデータサイエンスでソリューションを生み出しましょう。
データコンサルティングのご案内