@akazu

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

二次元配列の最大値と座標を求めたい

Pythonで、「二次元配列の値が最大となるindexとcolumnsの値を返すプログラム」を作りたいです。

データフレームとして読み込んだ以下のデータから、最大値:2.09e-5、またそのときのindex値:5、columns値:5となるようなプログラムを作りたいです。

image.png

(先ほどのデータをプロットすると以下のような図になります。)

image.png

できていること

以下がCSVのデータです。

2.16e-07,-1.40e-07,-1.39e-06,3.09e-07,2.22e-06,3.79e-06,4.63e-06,4.63e-06,3.97e-06,4.88e-06
2.62e-06,4.07e-07,1.41e-06,3.04e-06,5.21e-06,6.78e-06,7.35e-06,6.84e-06,6.04e-06,4.93e-06
1.87e-06,2.68e-06,4.16e-06,6.72e-06,9.01e-06,1.05e-05,1.09e-05,1.00e-05,8.17e-06,6.28e-06
2.85e-06,4.02e-06,6.92e-06,9.84e-06,1.23e-05,1.69e-05,1.40e-05,1.27e-05,1.04e-05,7.30e-06
3.18e-06,5.29e-06,8.62e-06,1.18e-05,1.81e-05,1.99e-05,1.97e-05,1.45e-05,1.19e-05,8.35e-06
3.07e-06,5.53e-06,9.04e-06,1.55e-05,1.91e-05,2.09e-05,2.07e-05,1.84e-05,1.25e-05,8.88e-06
2.66e-06,4.79e-06,8.15e-06,1.14e-05,1.78e-05,1.97e-05,1.97e-05,1.46e-05,1.21e-05,8.84e-06
2.05e-06,3.23e-06,6.17e-06,9.15e-06,1.17e-05,1.67e-05,1.38e-05,1.29e-05,1.09e-05,8.18e-06
1.18e-06,1.99e-06,3.48e-06,6.08e-06,8.48e-06,1.02e-05,1.08e-05,1.03e-05,8.85e-06,7.22e-06
2.63e-06,2.86e-07,1.24e-06,2.79e-06,5.00e-06,6.66e-06,7.42e-06,7.19e-06,6.52e-06,5.80e-06
df = pd.read_csv('ファイル名.csv', header=None)

データを読み込むことまではできています。ここから、上記のことがわかりません。pythonもプログラミングも初心者です。教えていただけないでしょうか。

0 likes

2Answer

numpy.ndarray.argmax()を利用して,最大の値を持つindexを取得します.ただし,デフォルト引数そのままでは1次元に平滑化したargmaxを得ることになるので,行数と列数を用いて次のように演算し,argmaxから最大値を持つ行と列を取得します.動作の可視化のために愚直実装も記述しておきます.

from io import StringIO
import pandas as pd

df = pd.read_csv(StringIO("""2.16e-07,-1.40e-07,-1.39e-06,3.09e-07,2.22e-06,3.79e-06,4.63e-06,4.63e-06,3.97e-06,4.88e-06
2.62e-06,4.07e-07,1.41e-06,3.04e-06,5.21e-06,6.78e-06,7.35e-06,6.84e-06,6.04e-06,4.93e-06
1.87e-06,2.68e-06,4.16e-06,6.72e-06,9.01e-06,1.05e-05,1.09e-05,1.00e-05,8.17e-06,6.28e-06
2.85e-06,4.02e-06,6.92e-06,9.84e-06,1.23e-05,1.69e-05,1.40e-05,1.27e-05,1.04e-05,7.30e-06
3.18e-06,5.29e-06,8.62e-06,1.18e-05,1.81e-05,1.99e-05,1.97e-05,1.45e-05,1.19e-05,8.35e-06
3.07e-06,5.53e-06,9.04e-06,1.55e-05,1.91e-05,2.09e-05,2.07e-05,1.84e-05,1.25e-05,8.88e-06
2.66e-06,4.79e-06,8.15e-06,1.14e-05,1.78e-05,1.97e-05,1.97e-05,1.46e-05,1.21e-05,8.84e-06
2.05e-06,3.23e-06,6.17e-06,9.15e-06,1.17e-05,1.67e-05,1.38e-05,1.29e-05,1.09e-05,8.18e-06
1.18e-06,1.99e-06,3.48e-06,6.08e-06,8.48e-06,1.02e-05,1.08e-05,1.03e-05,8.85e-06,7.22e-06
2.63e-06,2.86e-07,1.24e-06,2.79e-06,5.00e-06,6.66e-06,7.42e-06,7.19e-06,6.52e-06,5.80e-06"""), header=None)

data = df.values                         # numpy.ndarrayを取り出す

# 愚直実装(計7行)
mx = -1e10                               # 最大値を保存する変数mxを用意する.データにある値よりも小さい値で初期化する
i, j = -1, -1                            # 最大値のあるindexを保存する変数を用意する.
for row in range(data.shape[0]):
    for col in range(data.shape[1]):
        if mx < data[row, col]:          # これまでに見つけた最大値mxよりもdata[row, col]の方が大きかったら
            mx = data[row, col]          # 大きい方であるdata[row, col]で上書きする
            i, j = row, col              # 上書きした時点のrow, colを保存する

# スマートな実装(計3行)
argmax = data.argmax()                   # argmaxを求める. argmax = df.values.argmax() として1行にまとめて書いても良い
i = argmax // data.shape[1]              # 行を求める
j = argmax % data.shape[1]               # 列を求める
print(f"(row, col) = ({i}, {j})")        # (row, col) = (5, 5)
print(f"max = {data[i, j]}")             # max = 2.09e-05
print(f"max = {data.flatten()[argmax]}") # max = 2.09e-05 1次元に平滑化(flatten)した配列の最大値のあるindexがargmaxである

一般に最大値を持つindexを求める操作にはargmaxと名付けられるので覚えておくとよいでしょう.メソッドが用意されており短く書けるので,後者の実装の方を使われることをおすすめします.

また,逆に最小値を持つindexを求めるのはargminですし,値の大きさ順にindexを並べ替えた配列を得る操作はargsortと呼ばれます.

1Like

Comments

  1. @akazu

    Questioner

    わかりやすい説明ありがとうございます。実装することができました。

Your answer might help someone💌