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

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

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

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

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

Q&A

解決済

2回答

4391閲覧

Numpyのboolの配列のtureのところを抜き出して演算した後に、抜き出した部分に関連する部分をもう一度bool化して、もとのboolのtureのところに代入する

pepasuke623

総合スコア55

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

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

0グッド

0クリップ

投稿2020/02/06 11:43

編集2020/02/06 14:30

お世話になります。Numpyの操作が分からず、ご質問します。

実現したいこと

実現したいことを一言で表現すると
「floatが格納された1次元の配列に、閾値によってフィルタリングしてboolに変換した後に、もう一度違う値の閾値でフィルタリングしてboolに変換した後に、もとのboolの配列とマージする」ということをしたいです。

イメージとしては次のような感じです
1.まず、次のような数字データがあったとします。
イメージ説明

  --

2.このデータに対して、ある閾値(ここでは10.0)を超えるものと超えないものでbool化します。
イメージ説明

 --

3.TRUEのところだけ抜き出して、抜き出した部分を1.0倍するとします。(分かりにくいですが・・)
イメージ説明

 --

4.抜き出したデータから更に演算して新しい閾値を求めます。抜き出したデータからとある演算をして閾値が16.0になったとします。新しい閾値を用いて更にBool化します。
イメージ説明

  --

5.もとの「2.」のbool値のTRUEのところに「4.」の結果を代入する形で、もう一度boolの配列を作ってカラーマップで出力する。(今回はカラーマップで出力することが本質ではないので割愛します)
イメージ説明

例題

上記の説明では分かりにくいと思うので、次のような例題を考えます。(問題設定がやや強引なこと、加えて「実現したいこと」で例示したものと数字が違いますが、突っ込まないで頂ければと思います・・・)

  • とある工場で、『機械の稼働状況』と『電力消費量』の2種類のデータが得られた
  • この工場の電力消費量の基準値を超える時間帯を検出したい
  • まず電力消費量が基準料を超える時間帯を出力し、そのときの機械の稼働状況と電力消費量を出力する
  • 次に検出された時間帯の電力消費量は機械にかなり負担をかけた運転をしているものとして、電力消費量が基準料を超える時間帯の『機械の稼働状況』を平均して1/2をしたものゲインとして求めて、このゲインを電力消費量が基準料を超える時間帯の『電力消費量』に掛ける(複雑ですが、工場内で経験的に使われている計算だと思って下さい)
  • さらに、前の項目で求めたゲインを4乗して新しい基準値を求め、前の項目でゲイン倍した『電力消費量』が新しい基準値を超えているかどうかを判定する
  • 最終的にboolの配列を求める

最終形として、[false ,true ,false true ,false ,false]
となっていれば正解です.

試したこと

途中まで作成しましたが、次のとおりです。

python

1import numpy as np 2 3# numpyのarrayを作成:一時間ごとの機械の稼働状況。行は一時間ごと(6工場ある)、列は機械(2種類ある)の稼働状況を意味する 4data_array = np.array([[1.1, 1.2], 5 [2.1, 2.2], 6 [3.1, 3.2], 7 [4.1, 4.2], 8 [5.1, 5.2], 9 [6.1, 6.2]]) 10# 各時間帯における電力消費 11power_array = np.array([3.3 ,9.9 ,2.2 ,8.8 ,1.1 ,7.7]) 12 13# 電力消費が基準を超えているか判定する(ここでは閾値を5.0とする) 14v1_array = power_array > 5.0 15 16# 基準値を超える時間帯の「機械の稼働状況」と「電力消費」を出力する 17print(data_array[v1_array ]) 18print(power_array[v1_array ]) 19 20# 閾値を再計算する 21# 稼働状況の平均を更に2で割った数を割りかけする 22gain = data_array[v1_array ].mean() /2 23 24# 求めた値をもとの電力データにかける 25power2_array = power_array[v1_array] *gain 26 27# 閾値その2より大きいかどうかを求める(もともと16.0と書いてあったが、閾値は前段の計算結果によって変わることを強調するため、変更した) 28v2_array = power2_array > gain**4 29 30# v1_arrayのTUREのところにv2_arrayの結果をはめ込みたいのに、ここから先が分からない!!

やや複雑ですが、アイディアを頂ければと思います。

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

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

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

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

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

can110

2020/02/06 12:10

例題の結果として、どんな欲しいデータ値が欲しいのか、具体的なデータ例で提示ください。
guest

回答2

0

boolean maskではなくインデックスで取り扱ってうまく頑張るとできるかもしれません。ただし、こういうやり方はオーバーヘッドが多いので、素直にやるより遅い可能性もあります。

python

1>>> import numpy as np 2>>> d1 = np.array([1.8, 18.9, 8.1, 10.5, 15.6, 7.2, 18.2, 1.5]) 3>>> tmp1 = d1 > 10.0 4>>> tmp2 = np.where(tmp1) 5>>> idx = tmp2[0][d1[tmp1] > 16.0] 6>>> result = np.zeros(dtype=np.bool, shape=d1.shape) 7>>> result[idx] = True 8>>> result 9array([False, True, False, False, False, False, True, False], dtype=bool) 10

投稿2020/02/06 15:58

hayataka2049

総合スコア30935

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

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

hayataka2049

2020/02/06 15:58

can110さんの追記と思いっきり被った……
pepasuke623

2020/02/08 14:36

コメントありがとうございます!!こういう方法もあるんですね!勉強になりますm(_ _)m
guest

0

ベストアンサー

単純に元データ全体に対して2つの条件を判定し、その2つの結果をandしたらよいのではないでしょうか?

Python

1import numpy as np 2 3d1 = np.array([1.8, 18.9, 8.1, 10.5, 15.6, 7.2, 18.2, 1.5]) 4b2 = d1 > 10.0 # 条件1 5b3 = d1 > 16.0 # 条件2 6 7b5 = b2 & b3 8print(b5) # [False True False False False False True False] 9d5 = d1[b5] 10print(d5) # [18.9 18.2] 11 12 13# numpyのarrayを作成:一時間ごとの機械の稼働状況。行は一時間ごと(6工場ある)、列は機械(2種類ある)の稼働状況を意味する 14data_array = np.array([[1.1, 1.2], 15 [2.1, 2.2], 16 [3.1, 3.2], 17 [4.1, 4.2], 18 [5.1, 5.2], 19 [6.1, 6.2]]) 20# 各時間帯における電力消費 21power_array = np.array([3.3 ,9.9 ,2.2 ,8.8 ,1.1 ,7.7]) 22 23# 電力消費が基準を超えているか判定する(ここでは閾値を5.0とする) 24v1_array = power_array > 5.0 25 26# 閾値を再計算する 27# 稼働状況の平均を更に2で割った数を割りかけする 28gain = data_array[v1_array ].mean() /2 29 30# 求めた値をもとの電力データにかける 31power2_array = power_array *gain # 全体に対して求める 32 33# 閾値その2より大きいかどうかを求める 34v2_array = power2_array > 16.0 35 36# 両方を満たす結果 37b = v1_array & v2_array 38print(b) # [False True False True False False]

計算量を減らす方法

条件1を満たした要素のみ条件2を判定する例です。

Python

1import numpy as np 2 3d1 = np.array([1.8, 18.9, 8.1, 10.5, 15.6, 7.2, 18.2, 1.5]) 4i2 = np.where( d1 > 10) # この条件1を満たす要素のインデックス 5d3 = d1[i2] * 1.0 # 条件1を満たす要素のみ1.0倍 6 7# d3からいろいろ演算して新しい閾値16を得る 8 9b5 = np.zeros(len(d1), dtype=bool) 10b5[i2] = d1[i2] > 16 # 条件1を満たした要素のみ条件2を判定 11print(b5) # [False True False False False False True False]

例題についても同じ考えでコードを書いてみましたが、最終結果が求めたい結果になっているかは分かりません。

Python

1import numpy as np 2 3# numpyのarrayを作成:一時間ごとの機械の稼働状況。行は一時間ごと(6工場ある)、列は機械(2種類ある)の稼働状況を意味する 4# →工場は1つで2台の機械=列があり、6時間分=行のデータといった例のほうが分かりやすい? 5data_array = np.array([[1.1, 1.2], 6 [2.1, 2.2], 7 [3.1, 3.2], 8 [4.1, 4.2], 9 [5.1, 5.2], 10 [6.1, 6.2]]) 11 12# 各時間帯における電力消費 13power_array = np.array([3.3 ,9.9 ,2.2 ,8.8 ,1.1 ,7.7]) 14 15# 電力消費が基準を超えているか判定する(ここでは閾値を5.0とする) 16i1 = np.where( power_array > 5.0) 17 18# 基準値を超える時間帯の「機械の稼働状況」と「電力消費」を出力する 19print(data_array[i1]) 20#[[2.1 2.2] 21# [4.1 4.2] 22# [6.1 6.2]] 23print(power_array[i1]) # [9.9 8.8 7.7] 24 25# 閾値を再計算する 26# 稼働状況の平均を更に2で割った数を割りかけする 27gain = data_array[i1].mean() /2 28print(gain) # 2.075 29 30# 求めた値をもとの電力データにかける 31power2_array = power_array.copy() 32power2_array[i1] = power_array[i1] *gain # ここでは条件1を満たす要素だけ 33print(power2_array) # [ 3.3 20.5425 2.2 18.26 1.1 15.9775] 34 35# 閾値その2より大きいかどうかを求める(もともと16.0と書いてあったが、閾値は前段の計算結果によって変わることを強調するため、変更した) 36print(gain**4) # 18.538406640625006 37b2 = np.zeros(power_array.shape[0], dtype=bool) 38b2[i1] = power2_array[i1] > gain**4 39print(b2) # [False True False False False False]

投稿2020/02/06 12:09

編集2020/02/06 16:14
can110

総合スコア38341

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

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

pepasuke623

2020/02/06 14:41 編集

早速コメントを頂きありがとうございます!! この質問のポイントは、"最初に基準を超た電力消費量"を抜き出したあとに再計算して求めた基準値は、"最初に基準を超た電力消費量"にしか影響しないということなんですね。(ややこしいですが・・・) 例えば最初の基準値5.0を超えるのはpower_arrayの2個目と4個目と6個目の計3つのデータなのですが、2回目に基準値の判定する対象となるデータはこの3つのデータなんです。 教えていただいた方法ですと、例えば2回目の閾値が16.0ではなく0.1となったとき(今回の例題では0.1にはなりませんが、仮にそうなったとすると)、出力結果は[true ,true ,true true ,true ,true]となってしまいます。この場合もし1回目の閾値が5.0で2回目の閾値が0.1ならば[false ,true ,false true ,false ,true]と出力させたいのです。 (確かに問題設定が分かりにくいので、例題の文とプログラムを修正しました)
can110

2020/02/06 14:49 編集

> 出力結果は[true ,true ,true true ,true ,true]となってしまいます。 この出力結果とは実際に回答コードで試して最終的に得た結果でしょうか? ではなく2回目の(単独の)判定結果ではないでしょうか? 回答で伝えたかったことは、条件1は条件2の足切りだということです。 すなわち1回目の判定結果がFalseである要素は2回目のそれがどうであれFalseになります。したがって、結果としては2、4、6番目のみがTrueとなる結果が得られますが、これは正しい結果でしょうか?
pepasuke623

2020/02/06 15:13

ご回答ありがとうございます!いえ、コメント頂いた内容に関しては正しいです。私が勘違いしていました。m(_ _)m この例題はterateilに投稿するために簡略化していますが、実際はもっと配列の次元が高く、もっと長い経時データです。さらに『電力消費量』にゲインを掛ける部分(「# 求めた値をもとの電力データにかける」の直下の行)は、実際はもっと複雑な処理を行います。なので、なるべく計算を軽くしたいという考えが頭にあったので、条件1で足切して、残ったデータに演算処理をしてから元の配列に戻そうという発想をしていました。 教えていただいた方法を試してみます。ありがとうございます。
can110

2020/02/06 15:51

> なるべく計算を軽くしたいという考えが頭にあったので、条件1で足切して、残ったデータに演算処理をしてから元の配列に戻そうという発想をしていました。 回答に追記しました。 「実現したいこと」の例に対して計算量を減らす例です。 「例題」に関しても基本的に同じ考えで解けるはずです。
pepasuke623

2020/02/06 15:55

おお!boolの配列を先に作って条件を満たすものを当てはめるという方法ですね!色々とありがとうございます。m(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問