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

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

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

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

3回答

2011閲覧

matplotolibを使用した機械稼働状況グラフのリアルタイム更新

F91_

総合スコア16

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2021/08/23 13:12

機械稼働状況のグラフ更新を実現したい

ラズベリーパイに光センサーを繋ぎ、工場の加工設備のシグナルタワーの点灯パターンにより、機械稼働状況を計測しています。
時間帯によっての機械稼働状況をリアルタイムに可視化したいのでグラフをリアルタイムに更新したいのですが、以下の問題が発生しました。

発生している問題:過去のグラフデータがクリアされずに、新しいグラフが増え続けてしまう

イメージ説明

関係ないかと思いますが以下のようなエラーメッセージが出ています

エラーメッセージ /usr/lib/python3/dist-packages/matplotlib/axes/_base.py:3215: MatplotlibDeprecationWarning: The `xmin` argument was deprecated in Matplotlib 3.0 and will be removed in 3.2. Use `left` instead. alternative='`left`', obj_type='argument') /usr/lib/python3/dist-packages/matplotlib/axes/_base.py:3221: MatplotlibDeprecationWarning: The `xmax` argument was deprecated in Matplotlib 3.0 and will be removed in 3.2. Use `right` instead. alternative='`right`', obj_type='argument')

使用している該当のソースコード

python

1import time 2import japanize_matplotlib 3import RPi.GPIO as GPIO 4import datetime 5import pandas as pd 6import matplotlib.pyplot as plt 7import matplotlib.dates as mdates 8from io import StringIO 9from time import sleep 10 11dissolution=1 #計測分解能[s] 12time1=0 #0秒 13rate=0 14# MCP3208からSPI通信で12ビットのデジタル値を取得。0から7の8チャンネル使用可 15def readadc(adcnum,clockpin,mosipin,misopin,cspin): 16 if adcnum> 7 or adcnum<0: 17 return -1 18 19 GPIO.output(cspin,GPIO.HIGH) # I/Oが起きないようにCSを1にする 20 GPIO.output(clockpin,GPIO.LOW)# CLK を0に設定しておく 21 GPIO.output(cspin,GPIO.LOW)# I/Oを始めるためにCSを0にする 22 23 commandout=adcnum# adcnum は 0 (CH0)なので、commandout は 00000000 24 commandout |=0x18 # スタートビット+シングルエンドビット# 0x18 は 00011000 なので、commandout は 00011000 になる。 25 commandout<<=3 # commandout は 11000000 になる。この上位5ビットを使い、制御信号の 11000 を送る。 26 27 for i in range(5): 28 if commandout & 0x80: 29 GPIO.output(mosipin,GPIO.HIGH) 30 else: 31 GPIO.output(mosipin,GPIO.LOW) 32 commandout<<=1 33 GPIO.output(clockpin,GPIO.HIGH) 34 GPIO.output(clockpin,GPIO.LOW) 35 36 adcout=0 # データ保存変数 adcout の初期化 37 38 for i in range(13):# 13ビット読む(ヌルビット+12ビットデータ) 39 GPIO.output(clockpin,GPIO.HIGH) 40 GPIO.output(clockpin,GPIO.LOW) 41 adcout<<=1 42 if i>0 and GPIO.input(misopin)==GPIO.HIGH: 43 adcout |=0x1 44 GPIO.output(cspin,GPIO.HIGH) 45 return adcout 46 47#GPIOへアクセスする番号をBCMの番号で指定することを宣言 48GPIO.setmode(GPIO.BCM) 49 50# ピンの名前を変数として定義# Raspberry Pi のモードとして、GPIOの番号を物理番号ではなく役割番号で指定する 51SPICS=8 52SPIMISO=9 53SPIMOSI=10 54SPICLK=11 55# SPI通信用の入出力を定義 出力ピンなのか入力ピンなのか指定する 56GPIO.setup(SPICLK,GPIO.OUT) 57GPIO.setup(SPIMOSI,GPIO.OUT) 58GPIO.setup(SPIMISO,GPIO.IN) 59GPIO.setup(SPICS,GPIO.OUT) 60 61start=time.time() 62 63def plot_operation(fig, ax): 64 data=pd.read_csv('mydata'+nowday+'.csv', header=None, names=[0,1], index_col=0, parse_dates=True) 65 x=data.index 66 y=data.iloc[:,0] 67 d_today = datetime.date.today() 68 dt_start = datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0) 69 df_start = pd.DataFrame([[0, 0]], index=[dt_start]) 70 d_tomorrow = d_today + datetime.timedelta(days=1) 71 dt_end = datetime.datetime(d_tomorrow.year, d_tomorrow.month, d_tomorrow.day) 72 df_end = pd.DataFrame([[0, 0]], index=[dt_end]) 73 data = df_start.append([data, df_end]) 74 data = data.asfreq('min', fill_value=0) 75 76 plt.figure(figsize=(12.8, 4.8)) 77 plt.xlabel("時刻") 78 plt.ylabel("1=稼働,0=停止") 79 plt.bar(x,y,width=0.0007) 80 plt.gca().xaxis.set_major_locator(mdates.HourLocator(interval=1)) 81 plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M')) 82 plt.gca().set_xlim(xmin=datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0),xmax=dt_end) 83 plt.gca().set_yticks([0, 1]) 84 plt.tight_layout() 85 plt.draw() 86 plt.pause(1) 87 88fig = plt.figure(figsize=(12.8, 4.8)) 89ax = fig.add_subplot() 90now=datetime.datetime.now() 91now6=now-datetime.timedelta(hours=6)#24時〜30時を前日分として保存 92nowday='{0:%Y%m%d}'.format(now6)#日付でcsv保存するため 93 94while True: 95 try: 96 inputVal0=readadc(0,SPICLK,SPIMOSI,SPIMISO,SPICS)# CH0の信号を取得する プログラム運転(緑) 97 inputVal1=readadc(1,SPICLK,SPIMOSI,SPIMISO,SPICS)#アラーム(赤) 98 if inputVal0 > 2000 or inputVal1 > 2000:#on/offを判断する光量を変更(緑) 99 #print(inputVal0) 100 time1=time1+1 101 print('稼働中') 102 print(now.strftime('%H:%M')) 103 if time1==1: 104 plot_operation(fig, ax) 105 time1=0 106 107 else: 108 print('停止') 109 print(now.strftime('%H:%M')) 110 111 elapsed_time=time.time()-start #(処理時間)=(処理が終わった時間)ー(処理を始めた時間) 112 a=dissolution - elapsed_time 113 sleep(1) 114 start=time.time() 115 116 except FileNotFoundError: 117 continue 118 finally: 119 sleep(1) 120 121 122 123 124 125

読み取っているエクセルデータ

20:25 1 0
20:26 1 0
20:27 1 0
20:28 1 0
20:29 1 0
20:30 1 0
20:31 1 0
20:32 1 0
20:33 1 0
20:34 1 0
20:35 1 0
20:36 1 0
20:37 1 0
20:38 1 0
20:39 1 0
20:41 1 0
20:42 1 0
20:43 1 0
20:44 1 0
20:45 1 0
20:46 1 0
20:47 1 0
20:48 1 0
20:49 1 0
20:50 1 0
20:51 1 0
20:52 1 0
20:53 1 0
20:54 1 0
20:55 1 0
20:56 1 0
20:57 1 0
20:58 1 0
20:59 1 0
21:00 1 0
21:01 1 0
21:02 1 0
21:03 1 0
21:04 1 0
21:05 1 0
21:06 1 0
21:07 1 0
21:08 1 0
21:09 1 0
21:10 1 0
21:11 1 0
21:12 1 0
21:13 1 0
21:14 1 0
21:15 1 0
21:16 1 0
21:17 1 0
21:18 1 0
21:19 1 0
21:20 1 0
21:21 1 0
21:22 1 0
21:23 1 0
21:24 1 0
21:25 1 0
21:26 1 0

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

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

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

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

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

guest

回答3

0

python

1import time 2import japanize_matplotlib 3import RPi.GPIO as GPIO 4import datetime 5import pandas as pd 6import matplotlib.pyplot as plt 7import matplotlib.dates as mdates 8from time import sleep 9import matplotlib as mpl 10 11start=time.time() 12dissolution=1 #計測分解能[s] 13time1=0 #0秒 14rate=0 15# MCP3208からSPI通信で12ビットのデジタル値を取得。0から7の8チャンネル使用可 16def readadc(adcnum,clockpin,mosipin,misopin,cspin): 17 if adcnum> 7 or adcnum<0: 18 return -1 19 20 GPIO.output(cspin,GPIO.HIGH) # I/Oが起きないようにCSを1にする 21 GPIO.output(clockpin,GPIO.LOW)# CLK を0に設定しておく 22 GPIO.output(cspin,GPIO.LOW)# I/Oを始めるためにCSを0にする 23 24 commandout=adcnum# adcnum は 0 (CH0)なので、commandout は 00000000 25 commandout |=0x18 # スタートビット+シングルエンドビット# 0x18 は 00011000 なので、commandout は 00011000 になる。 26 commandout<<=3 # commandout は 11000000 になる。この上位5ビットを使い、制御信号の 11000 を送る。 27 28 for i in range(5): 29 if commandout & 0x80: 30 GPIO.output(mosipin,GPIO.HIGH) 31 else: 32 GPIO.output(mosipin,GPIO.LOW) 33 commandout<<=1 34 GPIO.output(clockpin,GPIO.HIGH) 35 GPIO.output(clockpin,GPIO.LOW) 36 37 adcout=0 # データ保存変数 adcout の初期化 38 39 for i in range(13):# 13ビット読む(ヌルビット+12ビットデータ) 40 GPIO.output(clockpin,GPIO.HIGH) 41 GPIO.output(clockpin,GPIO.LOW) 42 adcout<<=1 43 if i>0 and GPIO.input(misopin)==GPIO.HIGH: 44 adcout |=0x1 45 GPIO.output(cspin,GPIO.HIGH) 46 return adcout 47 48#GPIOへアクセスする番号をBCMの番号で指定することを宣言 49GPIO.setmode(GPIO.BCM) 50 51# ピンの名前を変数として定義# Raspberry Pi のモードとして、GPIOの番号を物理番号ではなく役割番号で指定する 52SPICS=8 53SPIMISO=9 54SPIMOSI=10 55SPICLK=11 56# SPI通信用の入出力を定義 出力ピンなのか入力ピンなのか指定する 57GPIO.setup(SPICLK,GPIO.OUT) 58GPIO.setup(SPIMOSI,GPIO.OUT) 59GPIO.setup(SPIMISO,GPIO.IN) 60GPIO.setup(SPICS,GPIO.OUT) 61 62def plot_operation(fig, ax): 63 data=pd.read_csv('mydata'+nowday+'.csv', header=None, names=[0,1], index_col=0, parse_dates=True) 64 x=data.index 65 y=data.iloc[:,0] 66 d_today = datetime.date.today() 67 dt_start = datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0) 68 df_start = pd.DataFrame([[0, 0]], index=[dt_start]) 69 d_tomorrow = d_today + datetime.timedelta(days=1) 70 dt_end = datetime.datetime(d_tomorrow.year, d_tomorrow.month, d_tomorrow.day) 71 df_end = pd.DataFrame([[0, 0]], index=[dt_end]) 72 data = df_start.append([data, df_end]) 73 data = data.groupby(level=0).last() 74 data = data.asfreq('min', fill_value=0) 75 plt.bar(x,y,width=0.0007,color="blue") 76 plt.gca().xaxis.set_major_locator(mdates.HourLocator(interval=1)) 77 plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M')) 78 plt.gca().set_xlim(left=datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0),right=dt_end) 79 plt.gca().set_yticks([]) 80 plt.draw() 81 plt.subplots_adjust(left=0.03, right=0.97, bottom=0.2, top=1) 82 plt.pause(1) 83 plt.clf() 84 85mpl.rcParams['toolbar'] = 'None' 86fig = plt.figure(figsize=(8.7, 3.5)) 87ax = fig.add_subplot() 88 89 90while True: 91 try: 92 inputVal0=readadc(0,SPICLK,SPIMOSI,SPIMISO,SPICS)# CH0の信号を取得する プログラム運転(緑) 93 inputVal1=readadc(1,SPICLK,SPIMOSI,SPIMISO,SPICS)#アラーム(赤) 94 now=datetime.datetime.now() 95 nowday='{0:%Y%m%d}'.format(now)#日付でcsv保存するため 96 if inputVal0 > 2000 or inputVal1 > 2000:#on/offを判断する光量を変更(緑) 97 #print(inputVal0) 98 time1=time1+1 99 print('稼働中') 100 print(now.strftime('%H:%M')) 101 print(time1) 102 if time1>=60: 103 plot_operation(fig, ax) 104 time1=0 105 106 else: 107 print('停止') 108 print(now.strftime('%H:%M')) 109 110 sleep(1) 111 112 except FileNotFoundError: 113 continue 114 except KeyboardInterrupt: 115 break 116

イメージ説明

投稿2021/08/25 14:14

編集2021/09/02 03:50
F91_

総合スコア16

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

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

0

ベストアンサー

plot_operation()関数について:

  • plt.figure(figsize=(12.8, 4.8))の行は不要
  • 代わりに ax.cla() の1行をその位置に挿入する
  • plt.gca().〜 は ax.〜 に置き換えて以下のようにする(書き換えなくても動くが、関数にするならこのほうがプログラムの意図※が明確になる)

ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
ax.set_xlim(xmin=datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0),xmax=dt_end)
ax.set_yticks([0, 1])
※ プログラムの意図:figure(fig)、Axes(ax)は最初にひとつだけ作って、関数では常にそれを引数で受け取って使い回すということ

  • 上と同じ理由で plt.bar(x,y,width=0.0007) も

ax.bar(x,y,width=0.0007)
とした方が良い

エラーメッセージについて:

  • エラーメッセージではなく警告メッセージ
  • ax.set_xlim(xmin=datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0),xmax=dt_end) を警告メッセージに従って以下のように変更する

ax.set_xlim(left=datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0),right=dt_end)

その他:

  • from io import StringIO は不要
  • start=time.time() が2箇所にあるが、

inputVal0=readadc(0,SPICLK,SPIMOSI,SPIMISO,SPICS)
の行の直前(try:の直後)に1箇所あればよいはず

  • finally 節はエラーが出ても出なくても必ず実行される。try 節の sleep(1) で1秒スリープし、さらに finally 節の sleep(1) で1秒スリープする結果、2秒間隔で while ループが実行されることになる。それでよいのかどうか。

よくない場合は、finally 節を削除して、finally 節の sleep(1) は except 節の continue の前に移動する

  • except 節は複数指定できるので、以下のような書き方ができる

python

1while True: 2 try: 3 ... 4 except FileNotFoundError: 5 continue 6 except KeyboardInterrupt: 7 break # ctrl+c でループを抜ける

投稿2021/08/23 14:06

編集2021/08/23 16:23
etherbeg

総合スコア1195

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

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

F91_

2021/08/23 14:11

ありがとうございます。明日以降読み込んでみます!
etherbeg

2021/08/23 14:15

とりあえず - plot_operation()関数のplt.figure(figsize=(12.8, 4.8))の行を削除 - 代わりに ax.cla() の1行をその位置に挿入 これだけでグラフ表示は改善すると思います。
F91_

2021/08/24 12:38

ValueError: cannot reindex from a duplicate axisというエラーが発生しました。昨日は発生しませんでした。ちなみに読み取っているデータは家にあるラズベリーパイで光を計測しています。 グラフには関係なくpandasの方のエラーだと思っています。xlimの作成方法がまだ理解出来ていないので助けていただけるとありがたいです。 start=time.time() が2箇所にあることですが、結論から言うとご指摘通り必要ありません。2箇所あったのは経緯がありまして・・何かのきっかけになるかもしれませんので一応説明します。 光を計測するプログラムにはstart=time.time() が2箇所必要で、そのプログラムを元にグラフのプログラムを作成したからです。sleep(1)となっていますが、本来はsleep(a)です。aがあることで計測時間のズレを解消する役割を果たしていました。稼働時間計測は微妙なズレも可能な限り避けたいので。 グラフは多少の時間ズレ、ここでは更新時間に絡んでくるだけなのでズレても大丈夫です。
etherbeg

2021/08/24 13:05

質問に関係ないことまで色々と口を出してしまい申し訳ありません。 また、現場の様子やプログラム全体がわからないまま口を出した結果、見当違いのことを申し上げることになって申し訳ありません。 ValueError: cannot reindex from a duplicate axis のエラーはおそらく > data = data.asfreq('min', fill_value=0) のところで発生していると思います。エラー出力を見てもらったらそうなっているはずです。 これは前回の質問で私がデータの補完を00:01始まりにした結果、24時を回っても機械が稼働していた時に同じ時刻のデータがダブってしまい、エラーになっていたのと同じエラーです。 > data = data.asfreq('min', fill_value=0) の直前(data = df_start.append([data, df_end]) の後)に > print(data) を入れてみるなどして一度データを確認してみてください。同じ時刻のデータが複数あると思います。 とりあえず > data = data.groupby(level=0).last() を間に挿入して > data = df_start.append([data, df_end]) > data = data.groupby(level=0).last() > data = data.asfreq('min', fill_value=0) とするだけでもエラーは回避できると思うので、それで対応してもらってもいいです。 > data = data.groupby(level=0).last() は時刻の重複するデータを削除するコードです(後に出てきた方のデータを残してあとは削除しています)。
etherbeg

2021/08/24 13:40

> dt_start = datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0) は7:00ちょうどのデータを作成し、 > dt_end = datetime.datetime(d_tomorrow.year, d_tomorrow.month, d_tomorrow.day) は翌日の0:00ちょうどのデータを作成して、 > data = data.asfreq('min', fill_value=0) でその間の欠けているデータを補完しているので、もし読み込んだデータに7:00ちょうど、翌日の0:00ちょうどのデータがあったら、データが重複して、エラーになります。 安全のために常に > data = data.groupby(level=0).last() を入れておいてもよいかもしれません。
F91_

2021/08/24 14:17

ありがとうございます。理解出来たと思います。 attributeerror: 'nonetype' object has no attribute 'cla'のエラーが発生しました。 自分の方でも対処方法を検討しますが、取り急ぎコメントします。
etherbeg

2021/08/24 14:26

エラー文だけでなくトレースバック (Traceback) をすべて教えていただけますか? こんな感じで↓ Traceback (most recent call last): File "/Users/xxxx/xxxx.py", line 26, in <module> data = data.asfreq('min', fill_value=0) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/frame.py", line 10323, in asfreq return super().asfreq( File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/generic.py", line 7562, in asfreq return asfreq( File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/resample.py", line 2048, in asfreq new_obj = obj.reindex(dti, method=method, fill_value=fill_value) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/util/_decorators.py", line 324, in wrapper return func(*args, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/frame.py", line 4767, in reindex return super().reindex(**kwargs) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/generic.py", line 4818, in reindex return self._reindex_axes( File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/frame.py", line 4592, in _reindex_axes frame = frame._reindex_index( File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/frame.py", line 4611, in _reindex_index return self._reindex_with_indexers( File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/generic.py", line 4883, in _reindex_with_indexers new_data = new_data.reindex_indexer( File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/internals/managers.py", line 670, in reindex_indexer self.axes[axis]._validate_can_reindex(indexer) File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/indexes/base.py", line 3785, in _validate_can_reindex raise ValueError("cannot reindex from a duplicate axis") ValueError: cannot reindex from a duplicate axis
F91_

2021/08/25 11:02

Traceback (most recent call last): File "/home/pi/b3.py", line 102, in <module> plot_operation(fig, ax) File "/home/pi/b3.py", line 74, in plot_operation ax.cla() AttributeError: 'NoneType' object has no attribute 'cla' エラー内容は少ないです。
etherbeg

2021/08/25 11:23

うーんaxにNoneが入っていること以外はわからないですね。 今は多分複数の変更をした状態だと思うので、いったん質問をした時の最初の状態に戻して、そこから少しずつ変えていってどこで動かなくなるか確認するのが良さそうですね。
F91_

2021/08/25 12:22 編集

Traceback (most recent call last): File "/home/pi/b3.py", line 101, in <module> plot_operation(fig, ax) File "/home/pi/b3.py", line 72, in plot_operation data = data.asfreq('min', fill_value=0) File "/usr/lib/python3/dist-packages/pandas/core/generic.py", line 6764, in asfreq fill_value=fill_value) File "/usr/lib/python3/dist-packages/pandas/core/resample.py", line 1591, in asfreq new_obj = obj.reindex(dti, method=method, fill_value=fill_value) File "/usr/lib/python3/dist-packages/pandas/util/_decorators.py", line 187, in wrapper return func(*args, **kwargs) File "/usr/lib/python3/dist-packages/pandas/core/frame.py", line 3566, in reindex return super(DataFrame, self).reindex(**kwargs) File "/usr/lib/python3/dist-packages/pandas/core/generic.py", line 3691, in reindex fill_value, copy).__finalize__(self) File "/usr/lib/python3/dist-packages/pandas/core/frame.py", line 3501, in _reindex_axes fill_value, limit, tolerance) File "/usr/lib/python3/dist-packages/pandas/core/frame.py", line 3512, in _reindex_index allow_dups=False) File "/usr/lib/python3/dist-packages/pandas/core/generic.py", line 3812, in _reindex_with_indexers copy=copy) File "/usr/lib/python3/dist-packages/pandas/core/internals.py", line 4414, in reindex_indexer self.axes[axis]._can_reindex(indexer) File "/usr/lib/python3/dist-packages/pandas/core/indexes/base.py", line 3576, in _can_reindex raise ValueError("cannot reindex from a duplicate axis") ValueError: cannot reindex from a duplicate axis 最初に戻しましたらエラー内容が変わりました。 自分なりに心当たりがある点で試していると、読み込むデータ量が増えるとエラーが発生するような気がしました。ちなみに上のエラーは7時~21時まで1分毎に漏れなくデータが入っているものを読み込んでいます。 データを一度消して21:05~21:00の間だけののデータにして読み込むとプログラムが動きます。 最初にグラフ更新が上手くいっていなかった時はデータ量が少ない状態で質問していました。 これまでは長い計測データでは試してはいなかったです。
etherbeg

2021/08/25 12:49 編集

これは2021/08/24 21:38のコメントですでに報告されているエラーですね。 「データを一度消して21:05~21:00程度のデータにするとプログラムが動きます」とのことですが、「動く」というのは、「過去のグラフデータがクリアされずに、新しいグラフが増え続けてしまう」が、エラーは出ずにとりあえずグラフは描画されている、という状態のことですか? それとも質問で解決したかったことは解決して、ちゃんと1枚のグラフの上でグラフが更新され続けている、ということですか? データの問題はグラフ描画の問題とは別の問題なので、そこは切り分けましょう。 もし前者なら、少ないデータ(エラーの出ないデータ)を使って、グラフの描画だけを先に解決させましょう。 もし後者なら、質問の問題は解決しているので、いったん解決済にした上で、続けてデータの問題についてお話ししましょう。コメントで続けてもいいですし、新たに質問を立ててもらっても構いません。
etherbeg

2021/08/25 13:10

前のコメントでもすでに述べましたが、「cannot reindex from a duplicate axis」というエラーは、インデックス(ここでは日時のデータ)に重複があることによって発生するデータです。 上では > data = data.groupby(level=0).last() を間に挿入して重複を削除する方法を案内したので、とりあえずこれで対応してもらっても構いません。 一番最初の質問をした時のプログラムに戻して、少ないデータ(エラーの出ないデータ)を使うか、もしくは上の重複削除のコードだけを挿入した上で、まず - plot_operation()関数のplt.figure(figsize=(12.8, 4.8))の行を削除 次に - 代わりに ax.cla() の1行をその位置に挿入 … と一つずつプログラムを変更しながら、その都度プログラムを動かして確認してください。 そしてどこで AttributeError: 'NoneType' object has no attribute 'cla' のエラーが出ているかを確定してください。
etherbeg

2021/08/25 13:18

もしくは、これも上で述べたことの繰り返しになりますが、 とりあえず - plot_operation()関数のplt.figure(figsize=(12.8, 4.8))の行を削除 - 代わりに ax.cla() の1行をその位置に挿入 これだけでグラフ表示は改善するはずなので、この時点でグラフが意図通り描画されていたら、あとはもう無理に変更してもらわなくてもいいです。その方がいいかもしれません。
F91_

2021/08/25 14:16 編集

色々とすみません。混乱していました。 これまでのコメントからコードを整理した所、上手くいきました。結局、axを使いこなせませんでした・・・時間のあるときに勉強してみます。前々から理解できていないので。また、ax.cla()を入れるとエラーが出てしまうので、入れませんでした。AttributeError: 'NoneType' object has no attribute 'cla' 完成プログラムを解決方法の所に入れておきます。⇒すみません。もしかしてここに入れるのはルール違反ですか?
etherbeg

2021/08/26 12:28

ルール違反ってことはないと思いますよ。自分なりに解決した場合に、どのように解決したのかを回答欄で報告するのは、誠実な態度だと思います。 ----- 以下は参考情報としてお聞きいただければ結構です。提案ぽいこともまた書いてしまっていますが、試すも試さないも、採用するもしないも、質問者さん次第です。 返信も、必要なければ、無理にしていただかなくても、大丈夫です。 "AttributeError: 'NoneType' object has no attribute 'cla'" の原因らしいものがわかりました。どうやら matplotlib のバージョンの問題のようです。 https://stackoverflow.com/questions/56632987/matplotlib-figure-figure-add-subplots-and-add-axes-return-none-instead-of-ax 上のリンクには解決方法も書いてありますが、もう ax は使わない方向でいくと決められているので、気にしなくていいでしょう。 それよりも、ax を使わなくても、ax.cla() と同じことができたことに今更ながら気がつきました。 plt.gca().cla() もしくは単に plt.cla() で同じことができます。入れる位置は plt.bar() を実行する前です。 〜.cla() を入れる場合と入れない場合の違いは、〜.cla() を入れない場合は、前に描画したグラフを消さずに、その上に新しいグラフを上書きしていくことです。 〜.cla() を入た場合は、前に描画したグラフを消してから、新しいグラフを描画します。 関数内の plt.figure() だけを削除したときに、グラフの色がその都度変わったのは、同じ場所に複数のグラフが重ねて描画されても区別がつくように、matplotlib が勝手にグラフの色を変えるからです。 今回は、重ねて描画されるグラフが同じグラフで、グラフの前の部分は次の回も残ったまま、一方向に伸びるだけなので、前のグラフは新しいグラフの下に完全に隠れるために、色だけが変わっているように見えました。 これは同じ日付内なら問題になりませんが、日付が変わって、データを読み取るファイルが変わった時に、不具合として現れます。本当は前日のグラフは消去して、新しく一からグラフが描かれるべきなのに、前の日のグラフが残ったままになるからです。 前回、「グラフ横軸の時間目盛りの最小、最大を設定したい」というタイトルで質問された時に、質問文に記載されたプロットのコードの中に、 plt.clf() という1行があったことを覚えていらっしゃるでしょうか。 このコードは例えていうと、グラフが書いてあるグラフ用紙を破って捨てて、新しい用紙にグラフを書き直すためのコードです。 一方、 plt.cla() は、グラフ用紙はそのままに、その上に書いてあるグラフだけを消しゴムで消して、新しくグラフを描き直すためのコードです。 もうひとつの問題は、前のグラフを消さずに、その上に新しいグラフを重ね書きをすることを延々と繰り返すために、繰り返したら繰り返しただけ、メモリを消費していくことです。 実際に問題になるようなメモリ消費量になるかどうかは確認してみないとわかりませんが(多分問題になるようなサイズではないのではと勝手に思ってますが)、常に起動して繰り返し実行し続けることを前提としたプログラムなので、ちょっと気にはなりますね。 --- data=pd.read_csv('mydata'+nowday+'.csv', header=None, names=[0,1], index_col=0, parse_dates=True) x=data.index y=data.iloc[:,0] d_today = datetime.date.today() dt_start = datetime.datetime(d_today.year, d_today.month, d_today.day, 7, 0) df_start = pd.DataFrame([[0, 0]], index=[dt_start]) d_tomorrow = d_today + datetime.timedelta(days=1) dt_end = datetime.datetime(d_tomorrow.year, d_tomorrow.month, d_tomorrow.day) df_end = pd.DataFrame([[0, 0]], index=[dt_end]) data = df_start.append([data, df_end]) data = data.groupby(level=0).last() data = data.asfreq('min', fill_value=0) plt.bar(x,y,width=0.0007,color="blue") この部分、一番最初にファイルからデータを読み込んで、それをxとyの変数に代入して、そして最後にそのxとyを使ってグラフを表示しています。 グラフ表示の直前に data = data.asfreq('min', fill_value=0) で、欠けている時刻を補完したデータを作成しているのですが、作成するだけで、作成したデータは使われていないことに気づかれていますか? 補完したデータは一切使われていないのに、グラフはちゃんと表示されていることから、今回のグラフに限って言えば、欠けているデータを補完しようがしまいが、グラフの描画には関係ない、ということが判明してしまいました! 必要なのは、時刻のデータをPythonの (Pandasの)日付型のデータとして読み込む(変換して読み込む)ことと、プロットの際にX軸は日付であると指示することの、ふたつだけでした。 欠けている時刻を補完して、抜けのないデータを作成する処理は、あってもなくても今回に限って言えば同じ、ということが判明してしまいましたが、データ補完のためのコードをどうするかは、質問者さん次第です。 エラーなく動いているのであれば、無駄なCPUを使ってはいますが、あろうが無かろうが一瞬で終わることなので、そのままにしておいてもいいし、なくてもいい処理があるのが気持ち悪ければ、削ってもいいし。 この件に関しては私の勘違いもあったので、ちょっと申し訳ないです。 ----- グラフの実際の画像を拝見しましたが、X軸のラベルの間隔が十分に取れていないので、ちょっと窮屈で見にくいですね。 07:00、08:00、09:00、10:00、11:00、12:00、13:00、14:00、… ではなく、 07、08、09、10、11、12、13、14、… でもいいかもしれません。 plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H'))
F91_

2021/08/26 12:51

ありがとうございました。これも宿題として時間のある時に読み込んでみます。
F91_

2021/08/28 02:19

先日現場で現場の方にグラフが見やすくなったと意見をもらえました!ありがとうございました。 それと今コメントを読んで理解しましたが、plt.clf()かclaがない状態でした。
F91_

2021/08/31 22:58

何度もすみません。plt.clf()を入れたのですが、前日分のグラフが消えずにそのまま上書きされています。おそらくplt.clf()を入れている位置が悪いのかもしれません。使用しているプログラムは自己解決方法の所を更新しておきます。もしくは新たに質問を立ち上げようと思います。
etherbeg

2021/08/31 23:23

plt.clf() は消して、 plt.bar(x,y,width=0.0007,color="blue") の前の行に plt.cla() を入れてみてください
etherbeg

2021/09/01 12:05

plt.cla()で前日分のグラフはちゃんと消えてくれましたか? しかしplt.cla()だったらグラフの土台は消えずに残ったままだと思ってたんですけど、夜中や休日を挟むと土台ごと消えてしまいますか?
etherbeg

2021/09/01 16:09

私の手元でテストした限りでは、plt.clf() をその位置に入れたプログラムでも、前のデータはちゃんと消えました。 修正してるファイルと実行してるファイルが別とかいうことはないでしょうか…
F91_

2021/09/01 23:18 編集

すみません!今週は諸事情によりレスポンスが遅めになってしまっています。 実行ファイルと修正ファイルが別ではないと思います。今確認しましたが、plt.clf()のままの場合は前日のグラフの土台も消えていませんでした.青バー表示も前日のままです。(plt.clfの位置は関数の最後のままです)今確認出来るのはそこまでですが、この状態から上書きされているのかももう一度確認してみます。 また、plt.cla()でどうなるのかも平行して確認します。
F91_

2021/09/02 00:29

おそらくですが、グラフ更新の問題ではなく読み取っているデータ自体が前日のままな気がします。
etherbeg

2021/09/02 01:55 編集

ホントだ、よく見たら now=datetime.datetime.now() nowday='{0:%Y%m%d}'.format(now) がループの外で1回実行されているだけなので、プログラムを最初に実行した日のファイルを永遠に取得し続けることになってますね。 返信はできる時にしていただいたらいいので別に気にしていただかなくて大丈夫ですよ。
F91_

2021/09/02 03:25

ありがとうございました。 now=datetime.datetime.now() nowday='{0:%Y%m%d}'.format(now) をループの中に入れて更新しました。
guest

0

whileの中で呼んでいる関数plot_operationの中で、毎回plt.figure(figsize=(12.8, 4.8))を実行すれば、最後に作ったfigureにdrawされるので、新しいグラフが増え続けるのは当然です。

それを止めたければ、plot_operationの中でのplt.figure(figsize=(12.8, 4.8))を消しましょう。

投稿2021/08/23 13:48

ppaul

総合スコア24666

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

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

F91_

2021/08/23 14:07

ありがとうございます。試した所、その通りでした。しかし、更新毎にplotされたグラフの色が変わってしまいます。対処方法は何かありまでしょうか?
ppaul

2021/08/23 15:23

明にグラフの色を指定すればよいでしょう。
F91_

2021/08/25 13:48

ご回答ありがとうございました。色に関しては初歩的なことでした。
F91_

2021/08/26 23:11 編集

plt.cla()が良さそうです。 理由は光を読み込んでいない時間(夜中、休日)にグラフが消えて、光を読込み再表示された時に元の場所(初期設定の位置)に表示されてしまうからです。面倒ですが、稼働表の隣にマウスでグラフのサイズと場所を合わせて移動させています。これも自動化したいですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問