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

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

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

JupyterLabは、Jupyter notebookの後継の対話型開発環境(IDE)です。データの可視化がインタラクティブで、プラグイン作成により新しいコンポーネントの追加および既存のコンポーネントも統合可能。サーバに閉じているため、データ分析に向いています。

Python

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

Q&A

1回答

609閲覧

Pythonでクラスを利用した場合の複数のグラフを重ねる方法

NMKN

総合スコア8

JupyterLab

JupyterLabは、Jupyter notebookの後継の対話型開発環境(IDE)です。データの可視化がインタラクティブで、プラグイン作成により新しいコンポーネントの追加および既存のコンポーネントも統合可能。サーバに閉じているため、データ分析に向いています。

Python

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

0グッド

0クリップ

投稿2022/11/30 07:34

編集2022/12/02 08:15

前提

ある実験データを用いた計算結果を極座標変換して等高線を表示したいと考えています。しかしまだ初学者であるため、まず係数などをでっちあげたものを極座標表示できるように練習しようと考えています。

実現したいこと

クラスを設定して表示した極座標グラフを複数重ねて等高線表示したい

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

クラスで行った場合の複数グラフの重ね方がわからない

該当のソースコード

python

1class Complex: 2 import math, matplotlib.pyplot as plt, numpy as np 3 def comp( self, r, d ): 4 return self.rnd( r * self.math.cos( self.math.radians(d) ) ), self.rnd( r * self.math.sin( self.math.radians(d) ) ) 5 6 def rnd( self, n, keta=-3 ): 7 return ( n // 10**keta ) * 10**keta 8 9 def plot( self, f ): # f = f(d) = r 10 xs, ys = [], [] 11 for i in range( 361 ): 12 try: 13 x, y = self.comp( f( self.math.radians(i) ), i ) 14 xs.append( x ) 15 ys.append( y ) 16 except: 17 pass 18 self.plt.figure( figsize=( 5, 5 ) ) 19 self.grid_plot( max(xs), max(ys) ) 20 self.plt.plot( xs, ys ) 21 return None 22 23 def grid_plot( self, x_m, y_m ): 24 z = self.math.sqrt( x_m**2 + y_m**2 ) 25 z_count = 0 26 dr = 10**(int( self.math.log( z, 10 ))) 27 while True: 28 if( z_count > z ): 29 break 30 xs, ys = [], [] 31 for i in range( 361 ): 32 x, y = self.comp( z_count, i ) 33 xs.append( x ) 34 ys.append( y ) 35 self.plt.plot( xs, ys, c='#dddddd' ) 36 z_count += dr 37 ds = [ 30, 45, 60, 120, 135, 150 ] 38 for d in ds: 39 x, y = self.comp( z, d ) 40 self.plt.plot( [ -1*x, x ], [ -1*y, y ], c='#dddddd' ) 41 self.plt.plot( [ 0, 0 ], [ -1*z, z ], c='#ff9999' ) 42 self.plt.plot( [ -1*z, z ], [ 0, 0 ], c='#ff9999' ) 43 return None 44 45comp = Complex() 46comp.plot(lambda d:3*(1+comp.math.cos(d)+comp.math.sin(d)+comp.math.cos(2*d)+comp.math.sin(2*d))) 47comp.plot(lambda d:6*(1+comp.math.cos(d)+comp.math.sin(d)+comp.math.cos(2*d)+comp.math.sin(2*d))) 48 49 # 修正案1 start --------------------------- 50 def plot1( self, *args): 51 xs, ys = [], [] 52 for i in range( 361 ): 53 try: 54 x, y = self.comp( *args( self.math.radians(i) ), i ) 55 xs.append( x ) 56 ys.append( y ) 57 except: 58 pass 59 60 61 self.plt.figure( figsize=( 5, 5 ) ) 62 self.grid_plot( max(xs), max(ys) ) 63 64 65 66 # 複数描写するには追加でplotをすればよい 67 self.plt.plot( xs, ys ) 68 69 # ★確認の為追加、不要なら削除 70 self.plt.show() 71 72 73 return None 74 # 修正案1 end ---------------------------

試したこと

クラスを利用したのが初めてなので正直ちんぷんかんではあります。
一旦て計算で出した式が3r(1+cosθ+sinθ+cos2θ+sin2θ)であったのでrの値を複数変えて重ねることによって等高線表示できないか考えました。しかし実行したところ(今回だと最後の二つ)、二つグラフが出てくる結果になったためクラスの内容を変える必要があると考えています。

補足情報(FW/ツールのバージョンなど)

修正案1の追加

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

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

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

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

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

guest

回答1

0

期待値はこんなグラフでしょうか?
イメージ説明

python

1class Complex: 2 import math, matplotlib.pyplot as plt, numpy as np 3 def comp( self, r, d ): 4 return self.rnd( r * self.math.cos( self.math.radians(d) ) ), self.rnd( r * self.math.sin( self.math.radians(d) ) ) 5 6 def rnd( self, n, keta=-3 ): 7 return ( n // 10**keta ) * 10**keta 8 9 def plot( self, f, dualFig=False): # f = f(d) = r 10 xs, ys = [], [] 11 for i in range( 361 ): 12 try: 13 x, y = self.comp( f( self.math.radians(i) ), i ) 14 xs.append( x ) 15 ys.append( y ) 16 except: 17 pass 18 self.plt.figure( figsize=( 5, 5 ) ) 19 self.grid_plot( max(xs), max(ys) ) 20 self.plt.plot( xs, ys ) 21 # ★確認の為追加、不要なら削除 22 self.plt.show() 23 24 return None 25 26 # ★追加 start --------------------------- 27 def dualPlot( self, f1 ,f2): 28 xs, ys = [], [] 29 for i in range( 361 ): 30 try: 31 x, y = self.comp( f1( self.math.radians(i) ), i ) 32 xs.append( x ) 33 ys.append( y ) 34 except: 35 pass 36 37 xs1, ys1 = [], [] 38 for i in range( 361 ): 39 try: 40 x, y = self.comp( f2( self.math.radians(i) ), i ) 41 xs1.append( x ) 42 ys1.append( y ) 43 except: 44 pass 45 self.plt.figure( figsize=( 5, 5 ) ) 46 self.grid_plot( max(xs1), max(ys1) ) 47 # 複数描写するには追加でplotをすればよい 48 self.plt.plot( xs1, ys1 ) 49 self.plt.plot( xs, ys ) 50 51 # ★確認の為追加、不要なら削除 52 self.plt.show() 53 54 55 return None 56 # ★追加 end --------------------------- 57 58 def grid_plot( self, x_m, y_m ): 59 z = self.math.sqrt( x_m**2 + y_m**2 ) 60 z_count = 0 61 dr = 10**(int( self.math.log( z, 10 ))) 62 while True: 63 if( z_count > z ): 64 break 65 xs, ys = [], [] 66 for i in range( 361 ): 67 x, y = self.comp( z_count, i ) 68 xs.append( x ) 69 ys.append( y ) 70 self.plt.plot( xs, ys, c='#dddddd' ) 71 z_count += dr 72 ds = [ 30, 45, 60, 120, 135, 150 ] 73 for d in ds: 74 x, y = self.comp( z, d ) 75 self.plt.plot( [ -1*x, x ], [ -1*y, y ], c='#dddddd' ) 76 self.plt.plot( [ 0, 0 ], [ -1*z, z ], c='#ff9999' ) 77 self.plt.plot( [ -1*z, z ], [ 0, 0 ], c='#ff9999' ) 78 return None 79 80 81comp = Complex() 82# comp.plot(lambda d:3*(1+comp.math.cos(d)+comp.math.sin(d)+comp.math.cos(2*d)+comp.math.sin(2*d))) 83# comp.plot(lambda d:6*(1+comp.math.cos(d)+comp.math.sin(d)+comp.math.cos(2*d)+comp.math.sin(2*d))) 84 85# ★追加 86comp.dualPlot(lambda d:3*(1+comp.math.cos(d)+comp.math.sin(d)+comp.math.cos(2*d)+comp.math.sin(2*d)),lambda d:6*(1+comp.math.cos(d)+comp.math.sin(d)+comp.math.cos(2*d)+comp.math.sin(2*d)))

星箇所が追加したコードです。
dualPlotのクラスを追加しています。
とりあえず重ねるだけの関数をクラスに追加しています。
グラフを重ねたいなら下記の公式ドキュメントが参考になります。
https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib-pyplot-plot

一人で作業している分にはこれでも問題ないですが、ちゃんと書くなら計算するクラスとグラフを書くクラスは分けたほうがわかりやすいかと思います。
あと今回追加したコードは、冗長なのでplot関数で描写せずに計算のみにして、複数プロットに対応した関数を追加するとより良いと思います。

投稿2022/11/30 08:41

tomoya0620

総合スコア34

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

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

NMKN

2022/12/01 01:41 編集

ご回答ありがとうございます。二つの場合の期待値はこうなります。ここで私が行いたいことはrの値を変更して多くのグラフを重ねる(等高線のようにする)ことなのですが、おそらくこのままだと3つ以上だとプロットできないと思います。もし力技でするならdualPlotに新しくxs2,xs3と追加すればできそうですが、そのほかにスマートな方法はご存知でしょうか?正直自分ではまだ初学者なため思いつきません... dualPlotの部分を見ると単純に増やすだけだはうまくいきそうにないですね...(12/1 10:41 編集)
tomoya0620

2022/12/01 02:27

おそらくこのままだと3つ以上だとプロットできないと思います。 →おっしゃる通り、dualPlotでは二つまでです。 なので、「複数プロットに対応した関数を追加するとより良いと思います。」 もし力技でするならdualPlotに新しくxs2,xs3と追加すればできそうですが、そのほかにスマートな方法はご存知でしょうか? →おっしゃる通り、xs2,xs3と引数を追加していくのは冗長なので、可変の引数にしましょう。 ここが参考になります。 https://note.nkmk.me/python-args-kwargs-usage/ dualPlotの部分を見ると単純に増やすだけだはうまくいきそうにないですね →その通りです。下記の箇所を別の関数に切りだし、ループ処理で回してあげましょう。関数の返却値はxs, ysが良いと思います。 xs, ys = [], [] for i in range( 361 ): try: x, y = self.comp( f1( self.math.radians(i) ), i ) xs.append( x ) ys.append( y ) except: pass xs1, ys1 = [], [] 返却値をもとにグラフを重ねて表示すればよいと思います。
NMKN

2022/12/02 08:24 編集

ご返信ありがとうございます。重ねて質問になり申し訳ないのですが、可変の引数にするのが応用が効いてスマートではないかと考えました。そこで質問なのですが(おそらくちんぷんかんぷんなことを言っていると思います)、引数としては *argsを使うと考えました。そこで今ここで行いたいのは様々なrを用意した計算式に入れてプロットし等高線を作ることです。しかし、dualPlotであると結局二つしかプロットできないためplot1など新しく定義する必要があると考えていますが、考え方は合っていますでしょうか?そしてもし新たに定義するとするならば、修正案1のようなコードのようにそのまま引数を使っても問題ないのでしょうか?(修正案1は該当のソースコード後半に載せています) また基本的事項の質問で大変申し訳ないのですが「下記の箇所を別の関数に切りだし、ループ処理で回してあげましょう」 この部分を具体的にどうのように行えば良いかわからないです。何をループさせれば良いのかというところかわかりません。 初学者なため、非常にわかりにくい返信となっているかもしれませんが、ご教授いただければ幸いです。 可変引数追加であれば都度r(ここでいうrは三角関数の(d)の係数のことです)を追加する必要があると思います。様々なrと申し上げましたが要は無限の等間隔のrを用いて等高線の幅の疎密を見たいわけなので、rをどのように可変するべきかというところも併せてご教授いただければ幸いです。(12/2 17:19編集) ごめんなさいrは三角関数の係数です... r(様々なr,,,,,ここを変えれば等高線ができる)を変えるにはr用のfor文を用意するのが妥当ですかね,,,,(12/2 17:24編集)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問