🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
NumPy

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

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

Q&A

解決済

2回答

4587閲覧

Python 3.x 二次元配列の全要素に対しての順位付け

退会済みユーザー

退会済みユーザー

総合スコア0

NumPy

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

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

0グッド

0クリップ

投稿2019/11/14 07:42

編集2019/11/14 08:37

二次元配列の全要素について順位付けがしたいです.
簡潔に述べると, 行や列だけでなく行列全体, 全要素で順位付けがしたいのですがスマートにできる方法などございますでしょうか.

※相互相関係数行列(下図)を二次元配列として使用しています.
イメージ説明

試したこと

Googleで検索して調べてみたところ,PandasのDataframeを使って順位付けできる関数があるらしく, まずnumpy配列をDataframeに変換します.

また,相互相関係数行列は
①対角成分が1
②対角線について対称
であり,これは順位付けの際に邪魔です.
-1にして順位付けの対象から外す必要があります.

Python

1#cvcは相互相関係数行列, N×Nのnumpy配列 2 3#numpy配列をDataframeに変換 4df = pd.DataFrame(cvc) 5 6#①,②の解消 7for i in range (N): 8 cvc[i,i]=-1 9 for j in range (i): 10 cvc[i,j]=-1 11 12# 確認用 13plt.figure(figsize=(8,6)) 14plt.title('Cross Corration', y=1.00, size=24) 15sns.heatmap(cvc, vmax=1, vmin=-1,center=0,cmap='rainbow')

イメージ説明

このようにとりあえずですが, 順位付けがスムーズにできそうなデータに整形できましたが... ここでpandasのDataframeの関数を確認してみます.

pandas.DataFrame.rank

確認するとどうやら行や列を対象にした順位付けしかできないようです.
最悪for文を使って全要素を比較してゴリ押すこともできなくはなさそうですが, パッとかける自信がないのと,きれいに結果をまとめることも考えると不適切に感じられます.

どうか, 知恵を貸して頂けないでしょうか.
よろしくお願いします.

追記

ただ順位付け,と書いてしまい語弊があったかもしれません.
配列及びデータフレームの形を崩さず,その配列の値を順位に書き直すようなものを順位付けとします.

例 [[1 2],[4,3]]を順位付けする場合 ⇒ [[4,3],[1,2]] と変換できること順位付けとします.

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

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

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

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

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

guest

回答2

0

ベストアンサー

わざわざ DataFrame化するのではなく、scipy.stats.rankdata()を使うとよいかと思います。

https://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.stats.rankdata.html

ただしこの関数は

  • 1次元データにしか適用できない
  • 昇順データのランクのみしか対応していない

為、

  • 「1次元データに変換->rankdataを適用->2次元データに戻す」 をする
  • 行列全体の正負を反転してから関数を呼ぶ

を行う必要があります。上記のように書くと面倒そうですが、実際の処理は

Python

1import scipy.stats as sts 2sts.rankdata((-arr).ravel(), method='min').reshape(arr.shape)

のように書けます

あと下半三角部を -1に置き換える作業ですが、ループを使わずに

Python

1arr[np.tril(np.ones(arr.shape)).astype(bool)] = -1

のように書くことができます。

以上まとめると以下のようになります。

Python

1import numpy as np 2import scipy.stats as sts 3 4# 乱数で適当な行列を作る 5arr = np.random.randint(0,10,(5,5)) 6arr[np.tril(np.ones(arr.shape)).astype(bool)] = -1 7print(arr) 8#[[-1 8 9 9 4] 9# [-1 -1 2 9 0] 10# [-1 -1 -1 6 7] 11# [-1 -1 -1 -1 4] 12# [-1 -1 -1 -1 -1]] 13ret = sts.rankdata((-arr).ravel(), method='min').reshape(arr.shape) 14print(ret) 15#[[11 4 1 1 7] 16# [11 11 9 1 10] 17# [11 11 11 6 5] 18# [11 11 11 11 7] 19# [11 11 11 11 11]]

投稿2019/11/15 03:07

magichan

総合スコア15898

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

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

退会済みユーザー

退会済みユーザー

2019/11/20 04:49

大変コメントが遅くなってしまい申し訳ありません. 教えてもらった通りに実行してみましたところ, 上手くいきました. 配列のfor処理についてもありがとうございました.
guest

0

並び替えなら以下の方法でできると思います。

python

1import numpy as np 2 3arr = np.random.randint(0, 100, size=(5, 5)) #2次元サンプル配列 4 5'''サンプル配列 6[[11 94 2 25 91] 7 [72 61 65 54 38] 8 [28 68 66 18 0] 9 [30 33 70 63 83] 10 [41 11 8 85 53]] 11''' 12arr_flat = arr.ravel() #配列を1次元化 13#[11 94 2 25 91 72 61 65 54 38 28 68 66 18 0 30 33 70 63 83 41 11 8 85 53] 14 15arr_sorted = np.sort(arr_flat) #ソート 16#[ 0 2 8 11 11 18 25 28 30 33 38 41 53 54 61 63 65 66 68 70 72 83 85 91 94]

投稿2019/11/14 08:07

takashim

総合スコア124

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

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

退会済みユーザー

退会済みユーザー

2019/11/14 08:33

すみません, ただ順位付けとしか書いてなかったため訂正しますが並び替えが目的ではないです. また,配列を一次元化してランクを出すというのは参照しづらい情報でしかないため今回は考えないものとします.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問