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

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

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

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

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

Q&A

解決済

3回答

648閲覧

matplotlibで複数のグラフの平均をとってグラフを描画する方法がわかりません。

onomatobee

総合スコア2

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

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

0グッド

0クリップ

投稿2023/02/07 02:18

編集2023/02/07 03:19

実現したいこと

  • 複数のグラフの平均をとって一つのグラフを出力する。

前提

ここに質問の内容を詳しく書いてください。

pythonで以下のようにネットワーク上のSIRモデルをシミュレーションすることを目指しております。最後、10回シミュレーションを行ってデータを重ねてグラフを描画するところまでは完了しました。しかし、その10個のグラフの平均をとって一つのグラフを作成する方法がよくわかりません。

発生している問題・エラーメッセージ

白紙のグラフが出力されました。

該当のソースコード

python

1import matplotlib.pyplot as plt 2import numpy as np 3import networkx as nx 4 5#ネットワークの設定。今回はBAモデル 6N=10000 #人口 7M=5 #次数 8G=nx.barabasi_albert_graph(N,M) 9 10#SIRモデルのシミュレーションを定義 11class SIR: 12 def __init__(self, G, beta, gamma): #ネットワーク、感染率、回復率を定義 13 self.G = G 14 self.beta = beta 15 self.gamma = gamma 16 17 def run(self, seed=[], num_steps = 1, sentinels = [], immunization_rate = 0.0, immunized_nodes = []): 18 #ネットワーク上の初期状態での免疫保持者をランダムに決定する。今回は0人。 19 if len(immunized_nodes) == 0: 20 immunized = set(np.random.choice(self.G.nodes(), 21 size=int(immunization_rate*len(self.G.nodes())), 22 replace=False)) 23 else: 24 immunized = immunized_nodes 25 26 # 初期状態でのIをランダムで決定する。 27 if len(seed) == 0: 28 seed = [np.random.choice(list(set(self.G.nodes()).difference(immunized)))] 29 30 #S,I,Rの初期状態 31 I_set = set(seed) 32 S_set = set(self.G.nodes()).difference(I_set).difference(immunized) 33 R_set = set() 34 35 t = 0 36 37 StoI = set(seed) 38 ItoR = set() 39 40 sentinels_t = {} 41 for sen in sentinels: 42 sentinels_t[sen] = 0 43 44 #I>0の場合、感染症が伝播 45 while len(I_set) > 0: 46 for i in I_set.copy(): 47 for s in set(self.G.neighbors(i)).intersection(S_set).copy(): 48 if np.random.uniform() < self.beta: 49 S_set.remove(s) 50 I_set.add(s) 51 StoI.add(s) 52 53 if sentinels_t.get(s) != None: 54 sentinels_t[s] = t 55 56 #回復率に従ってIをRに変化 57 if np.random.uniform() < self.gamma: 58 I_set.remove(i) 59 R_set.add(i) 60 ItoR.add(i) 61 62 t += 1 63 if t % num_steps == 0 or len(I_set) == 0: 64 yield({'t': t, 'S':S_set, 'I':I_set, 'R':R_set, 'StoI':StoI, 'ItoR':ItoR, 'sentinels': sentinels_t}) 65beta = 0.2 #感染率 66gamma = 0.1 #回復率 67 68peak_times = [] 69 70#複数のデータを一つのグラフにまとめる。 71plt.figure() 72ax = plt.subplot(111) 73ax.set_prop_cycle('color', ['green', 'red', 'blue']) 74 75#試行回数を決定。L回シミュレーションしてデータを重ねる。 76L=10 77for i in range(0,L): 78 sir = SIR(G, beta = beta, gamma = gamma) 79 ave = [] 80 sum=0 81 for r in sir.run(num_steps=1): 82 sum_S=sum+len(r['S']) 83 sum_I=sum+len(r['I']) 84 sum_R=sum+len(r['R']) 85 ave.append([sum_S, sum_I, sum_R]) 86 87 88 #データをプロット 89 plt.plot(ave) 90 91#結果をプロット 92plt.title("Infection On Network") 93plt.legend(['S', 'I', 'R']) 94plt.xlabel("day") 95plt.ylabel("Population") 96plt.show()

試したこと

numpyで平均値を取る関数を用いたりしましたが、うまくいきませんでした。
有識者の方、どうか解決法をご教授いただけませんでしょうか。

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

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

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

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

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

can110

2023/02/07 02:59

まずは1回だけシミュレーションした結果は正しく描画できるでしょうか? 提示コードをみる限り - sum=0 はつねに0のままのようだがそれでよい? -「sum_S=~」行のインデントは正しいか? - resは利用されていないがそれでよい? など、ところどころ意図が読めない部分がありますので、そのあたりの説明を追記すると回答得られやすくなるかと思います。
onomatobee

2023/02/07 03:14

はい、1回だけ行った場合は正しく描画できました。 10回ほどシミュレーションを行った後、その平均を取る方法をご教授いただければと思います。
onomatobee

2023/02/07 03:17

ご質問ありがとうございます。 私なりに当該箇所を修正させていただきました。
melian

2023/02/07 03:50 編集

sum_S=sum+len(r['S']) sum_I=sum+len(r['I']) sum_R=sum+len(r['R']) の部分ですが、これは、以下の様にするのではないでしょうか? sum_S = sum_I = sum_R = 0 for r in sir.run(num_steps=1):  sum_S += len(r['S'])  sum_I += len(r['I'])  sum_R += len(r['R']) total = sum_S + sum_I + sum_R ave.append([sum_S/total, sum_I/total, sum_R/total])
onomatobee

2023/02/07 03:52

ありがとうございます。 ぜひ試させていただきたいと思います。
onomatobee

2023/02/07 06:14

試してみたのですが、どうやら時間tに関しても平均値が取られてしまっている様です‥。
guest

回答3

0

python

1#試行回数を決定。 2L = 10 3sumup, length = [], [] 4for _ in range(L): 5 sir = SIR(G, beta = beta, gamma = gamma) 6 for i, r in enumerate(sir.run(num_steps=1)): 7 sum_S, sum_I, sum_R = len(r['S']), len(r['I']), len(r['R']) 8 if i < len(sumup): 9 sumup[i][0] += sum_S 10 sumup[i][1] += sum_I 11 sumup[i][2] += sum_R 12 length[i] += 1 13 else: 14 sumup.append([sum_S, sum_I, sum_R]) 15 length.append(1) 16 17#データをプロット 18ave = [[v / l for v in s] for s, l in zip(sumup, length)] 19plt.plot(ave)

イメージ説明

投稿2023/02/07 08:06

melian

総合スコア19714

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

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

0

ご回答本当にありがとうございます。
早速試させていただいたのですが、やはり10個のデータが別々に出力されてしまう様です…。

投稿2023/02/07 08:15

onomatobee

総合スコア2

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

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

0

ベストアンサー

10個のグラフの平均をとって一つのグラフを作成する方法

numpyやmatplotlibに便利な関数は存在しないとおもうので、地道に各試行結果を計算するほかないと思います。

75行目以下を下記コードに変更するのでいかがでしょうか?
※平均のグラフを出すことを目標としたので、グラフの色などの設定は適当です。

Python

1import pandas as pd 2L=10 3res_for_ave = [] #各試行の結果を保存しておくためのリスト 4for i in range(0,L): 5 sir = SIR(G, beta = beta, gamma = gamma) 6 res = [] 7 ave = [] 8 sum=0 9 for r in sir.run(num_steps=1): 10 res.append([len(r['S']), len(r['I']), len(r['R'])]) 11 plt.plot(res) 12 res_for_ave.append(res) #試行結果を保存 13 14# pandasで保存したデータを加工し、平均を算出 15df = pd.DataFrame(res_for_ave) 16df = df.T 17df = df.fillna(0) 18x = np.arange(0,len(df)) #時間 19ave_s = [] #S 20ave_i =[] #I 21ave_r = [] #R 22for row in range(len(df)): #時間でLoop 23 count_sum_s = 0 24 count_sum_i = 0 25 count_sum_r = 0 26 count_len = L 27 for col in df.columns: #試行回数分でLoop 28 if df[col][row] == 0: 29 count_len -= 1 30 else: 31 count_sum_s += df[col][row][0] #S 32 count_sum_i += df[col][row][1] #I 33 count_sum_r += df[col][row][2] #r 34 ave_s.append(count_sum_s/count_len) 35 ave_i.append(count_sum_i/count_len) 36 ave_r.append(count_sum_r/count_len) 37plt.plot(x,ave_s, label = "S") 38plt.plot(x,ave_i, label = "I") 39plt.plot(x,ave_r, label = "R") 40plt.title("Infection On Network") 41plt.legend(['S', 'I', 'R']) 42plt.xlabel("day") 43plt.ylabel("Population") 44plt.show()

投稿2023/02/07 06:46

TKMoon

総合スコア79

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

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

onomatobee

2023/02/07 08:22

再度試したところ、無事解決することができました! 本当にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問