質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

3316閲覧

python ヒストグラムのアニメーション

kouheichild

総合スコア18

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

5クリップ

投稿2019/01/30 13:40

編集2019/01/30 14:24

前提・実現したいこと

pythonでヒストグラムが動くアニメーションを作りたいです.
具体的には,平均15,標準偏差2(固定)で平均が15から0に移動するアニメーションを作りたいです.
下記のコードを実行したのですが、静止画になってしまい、うまくアニメーションが作成できません.

https://qiita.com/yubais/items/c95ba9ff1b23dd33fde2
また記載したコードは、上記のページに記載されたコードを参考にしました。このページに記載されたコードを流した場合はアニメーションが作動します。

大変恐縮ですが,ご教授お願いいたします.

該当のソースコード

python

1import numpy as np 2import matplotlib.pyplot as plt 3import matplotlib.animation as animation 4from scipy import stats 5 6fig = plt.figure() 7ims=[] 8a =np.linspace(start=15,stop=0,num=16) 9for i in a: 10 np.random.seed(1) 11 rand = stats.norm.rvs(i,2,7321) 12 im = plt.hist(rand) 13 ims.append(im) 14 15# 16枚のプロットを 1000ms ごとに表示 16ani = animation.ArtistAnimation(fig, ims, interval=1000) 17plt.show() 18
melian👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

firedfly

2019/01/30 13:52

こんにちは。 「うまくアニメーションが作成できません」というだけでは伝わりません。 エラーが出るのか、エラーは出ないが望む動作にならないのか。自分で試したことはなにか。 よい回答を望むなら、出せる情報はすべた出してよい質問を心がけましょう。
kouheichild

2019/01/30 14:17

firedfly様 ご回答ありがとうございます。 不十分な質問で申し訳ございません。 ご指摘ありがとうございます。 この場をお借りして補足させていただきますと、 記載したコードを実行すると、静止画になってしまいます。アニメーションがうまく機能しないことが問題です。 https://qiita.com/yubais/items/c95ba9ff1b23dd33fde2 また記載したコードは、上記のページに記載されたコードを参考にしました。このページに記載されたコードを流した場合はアニメーションが作動します。
firedfly

2019/01/30 14:21

素晴らしい補足をありがとうございます。 時間に余裕のある時でよいので、質問本文にもぜひご追記ください。 そうすれば私以外の回答者が来たときに見やすいですので。
guest

回答2

0

ベストアンサー

原因

自分も原因がわからなかったので少し実験してみました。
(A) im = plt.hist(rand)
質問者さんのコードでは(A)となっていますが、この状態で実行すると「ウィンドウに静止画が表示される」というよりは「matplotlibでエラーが発生している」ことに気づきます。下記はPyCharmで実行してみたときのコンソールの情報です。

python

1C:\Users\ksoh\PycharmProjects\teratail\venv\Scripts\python.exe C:/Users/ksoh/PycharmProjects/teratail/t05_animation.py 2Traceback (most recent call last): 3 File "C:\Users\ksoh\AppData\Roaming\Python\Python37\site-packages\matplotlib\cbook\__init__.py", line 215, in process 4 func(*args, **kwargs) 5 File "C:\Users\ksoh\AppData\Roaming\Python\Python37\site-packages\matplotlib\animation.py", line 999, in _start 6 self._init_draw() 7 File "C:\Users\ksoh\AppData\Roaming\Python\Python37\site-packages\matplotlib\animation.py", line 1520, in _init_draw 8 artist.set_visible(False) 9AttributeError: 'numpy.ndarray' object has no attribute 'set_visible'

一方、リンク先では
(B) im = plt.plot(rand)
のようにplot関数の結果を蓄積してアニメーションしていますがそちらだと上記のようなエラーは出ずにアニメーションが表示されますね。

つまりplt.plotの結果のリストはアニメーションできて、plt.histの結果のリストはアニメーションできないということのように思えました。

もう一度先のエラーメッセージを見ると・・・

matplotlibの中でartistという変数にnumpy.ndarrayが格納されていたため「numpy.ndarrayオブジェクトにはset_visibleなんてメソッドないです」と言われてます。確かにnumpyの配列にそんなメソッドはないです。ArtistAnimationのリファレンスを見ると
https://matplotlib.org/api/_as_gen/matplotlib.animation.ArtistAnimation.html

artists : list
Each list entry a collection of artists that represent what needs to be enabled on each frame. These will be disabled for other frames.

とあり、第二引数に渡すのはmatplotlibのartist(多分グラフを構成するオブジェクト群)のリストらしいことがわかります。そのartistには必ずset_visibleというメソッドがあるはずだということなのでしょう。

さてplotのリファレンスを見ると
https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html

Returns:
lines
A list of Line2D objects representing the plotted data.

さらにhistのリファレンスを見ると
https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html

Returns:
n : array or list of arrays
The values of the histogram bins. ...
bins : array
The edges of the bins. ...
patches : list or list of lists
Silent list of individual patches used to create the histogram or list of such list if multiple input datasets.

とあり、plotの方はグラフを構成するLine2Dのリストを返すのに対してhistはn, bins, patchesの3つの要素を持つtupleが返されグラフを構成するオブジェクトは3つ目のpatchesに当たるように見えました。

対処(推測)

以上のことから「多分histが返す3つ目の要素をリストにすればアニメーションできるんじゃないか」と推測しました。そのとおりやってみると実行時例外はおきなくなりアニメーションが表示されました。

python

1import numpy as np 2import matplotlib.pyplot as plt 3import matplotlib.animation as animation 4from scipy import stats 5 6fig = plt.figure() 7artists = [] 8a = np.linspace(start=15, stop=0, num=16) 9for i in a: 10 np.random.seed(1) 11 rand = stats.norm.rvs(i,2,7321) 12 n, bins, artist = plt.hist(rand) 13 artists.append(artist) 14 15# 16枚のプロットを 1000ms ごとに表示 16ani = animation.ArtistAnimation(fig, artists, interval=1000) 17plt.show()

余談:
例えばPyCharmのようなコードの誤りを事前に警告してくれるような親切なIDEを用いて、次の図のように警告を発してくれればまだ気づきやすかったと思います。

fig.1

しかし残念ながらPythonの超有名ライブラリーであるnumpyもmatplotlibもPython3.5でサポートされた型ヒントをサポートしていません。(Python3.5より前のバージョンを利用しているユーザーがまだまだ多いということを考えればサポートできないのも当然といえましょう。なお、上の図はわざわざ自分で型ヒント付きの定義をしてPyCharmに誤りを警告させてみたものです)

それゆえ引数の型があっているかについてIDEのサポートは期待できず、当然自分が使う関数の仕様をドキュメントにより調べようとするわけですが、Pythonではコード上に型の宣言がないことが多いですし、そもそも動的型付け言語であることを最大限生かした関数、すなわち「スカラーの数値でも、strでも、tuple/list/ndarrayでもいいよー」的な、良く言えば柔軟、悪く言えばチャランポラン(?)な関数も多く、ドキュメントを見てさえすぐに間違いに気づけるとは限りません。

逆に言えばリファレンスをよく見ずになんとかなるものではないといえましょう。単にサンプルを見てそれを応用しようとしても本件のような落とし穴に落ちやすいと思います。

質問者さんがリファレンスをどのくらい見ておられるか、どのくらいプログラムの実行結果に関する情報に注意を向けているか不明ですが

  • ライブラリーが発する例外/警告メッセージを注意深く見て、その意味を想像する
  • リファレンスを見て仕様を把握しようとする
  • ときに実験によって原因究明に努める

そういう努力をしないと解決に近づくことはおぼつかないと思います。今回の回答があってるかどうか完全な自身はないですが、少なくとも前述のことをせずには原因に近づける気がしません。「どういうコードを書けばよいか」が知りたい情報だとは思いますが、「それをどのようにして得るか」の方が本質的にはもっと重要と考えます。質問する際にも「どういうところまで調べたか」を言っていただけると閲覧者のみなさんに有用な質問になると思います。

投稿2019/01/30 19:32

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

firedfly

2019/01/30 23:00

高評価をひとりで5個つけて永久保存して都度参照したいくらいの良回答です。 「回答者が望む情報はなにか」や「回答を得るためにどう試行錯誤できるのか」など共通する方法論は、teratail Wikiを作って書いて都度リンクを貼りたいですね。
kouheichild

2019/01/31 05:19

KSwordOfHastem 様 ご回答ありがとうございます. 質問の答えだけでなく,その原因・それを見つけるまでの経緯・考え方までご教示ありがとうございます. 当方,リファレンスは実は一度も見たことがなく,ネットに転がっているコードを応用させることばかりをしてしまっておりました. KSwordOfHastem 様 のお言葉を受け,今後は自分で原因を探る努力をしたいと思います. ご多忙の中,ご回答いただきありがとうございました. 今後teratailを利用させていただく際にも,ご縁がありましたら再度ご教示いただけたら幸いです. 何卒よろしくお願いいたします.
KSwordOfHaste

2019/01/31 12:39

自分もArtistAnimationについてもやもやしていたので本質問をきっかけに調べた結果たまたまなにがしかつかめた気がしたので調べたことを書いてみた次第です。それがなんらかのヒントになってくれれば幸いです。 正直なところ本質問がきっかけである程度スッキリしたので自分自身もこの質問に助けられました。 コメントおよせくださいましてありがとうございました。>質問者さん、firedflyさん
guest

0

FuncAnimation を使ったらできました。

matplotlib のデフォルトのヒストグラムは少し味気ないので、サンプルコードでは seaborn を併用しています。

python

1import matplotlib.pyplot as plt 2import numpy as np 3import seaborn as sns 4from matplotlib.animation import FuncAnimation 5from scipy import stats 6# jupyter notebook の場合、コメントアウト 7# %matplotlib nbagg 8 9sns.set(style='ticks') 10np.random.seed(42) 11 12locs = np.linspace(15, 0, 16) # 平均 13fig, ax = plt.subplots(figsize=(4, 4)) 14 15def plot(i, locs): 16 data = stats.norm.rvs(loc=locs[i], scale=2, size=7321) 17 18 ax.clear() # 図をクリア 19 # kde=False 密度関数描画しない、bins=50 ビンの数、norm_hist ヒストグラム正規化 20 sns.distplot(data, bins=50, ax=ax, kde=False, norm_hist=True) 21 # ax.hist(data) setborn 使わない場合はこっち 22 ax.set_ylim(0, 0.3) # y 軸範囲固定 23 24 25# 16枚のプロットを 1000ms ごとに表示 26anim = FuncAnimation(fig, plot, frames=len(locs), fargs=(locs,), repeat=True) 27anim.save('animation.gif', writer='imagemagick') 28 29plt.show()

イメージ説明

投稿2019/01/30 16:47

編集2019/01/30 16:50
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kouheichild

2019/01/31 05:23

tiitoi様 ご回答ありがとうございます. 大変丁寧なご回答ありがとうございます. 今後ともどうかよろしくお願いいたします.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問