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

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

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

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

Python

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

Q&A

解決済

4回答

2009閲覧

Python 二次元配列から、任意のデータを探す

O.K.

総合スコア30

NumPy

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

Python

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

0グッド

1クリップ

投稿2018/06/11 10:12

np.arrayの二次元配列(要素数は5)から要素①,要素②,要素③,要素④の組み合わせが例えば、1,2,3,4の列の要素⑤を取得する場合はどうすればいいですか?

下記のようにすれば要素⑤の取得は可能ですが、何万回と繰り返す部分なのでもっと速く取得できる方法を教えてください。

Python

1for i in array: 2 if i[0] == 1 and i[1] == 2 and i[2] == 3 and i[3] == 4: 3 print(i[4])

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

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

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

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

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

guest

回答4

0

ベストアンサー

こういうのはどうでしょうか。

python

1import timeit 2import numpy as np 3 4A = np.arange(50000).reshape((10000, 5)) 5 6def f0(a,b,c,d): 7 """質問文の方式 8 """ 9 lst = [] 10 for i in A: 11 if i[0] == 1 and i[1] == 2 and i[2] == 3 and i[3] == 4: 12 lst.append(i[4]) 13 # print(lst) 14 lst 15 16def f1(a,b,c,d): 17 """私が考えた方式。一列ずつ見て、削っていきます 18 こうすると比較の回数がケチれて(本質的には短絡評価と同じことをしています)速いはずです 19 """ 20 tmp = A 21 for i, eqv in enumerate([a,b,c,d]): 22 tmp = tmp[tmp[:,i] == eqv] 23 24 # print(tmp[:,-1]) 25 tmp[:,-1] # 計測時にprintしたくなかったので 26 27def f2(a,b,c,d): 28 """mkgreiさんの方式 29 """ 30 idx = (A[:, :4]==np.array([a,b,c,d])).all(axis=-1) 31 # print(A[idx, -1]) 32 A[idx, -1] # 計測時にprintしたくなかったので 33 34print(timeit.timeit(lambda : f0(0,1,2,3), number=1000)) 35print(timeit.timeit(lambda : f1(0,1,2,3), number=1000)) 36print(timeit.timeit(lambda : f2(0,1,2,3), number=1000)) 37""" 38私の環境だと、 393.3318773460000557 400.06133379499988223 410.27946032499994544 42くらい 43"""

投稿2018/06/11 11:05

編集2018/06/11 11:17
hayataka2049

総合スコア30933

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

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

mkgrei

2018/06/11 11:12

なるほど、コケを落としていくように絞り込んでいくんですね。 4倍以上も速い…
hayataka2049

2018/06/11 11:13

これだと相手のデータがでかいほど効きます。小さいとどこかでオーバーヘッドに負けて逆転するはずです。 本当はぜんぶnumpy上でやろうと思ったんですが、うまく書けなかったのでとりあえずただのforで
O.K.

2018/06/11 11:53

回答ありがとうございます。 tmp = tmp[tmp[:,i] == eqv] の部分がよくわかりません。 どうなっているのですか?
hayataka2049

2018/06/11 11:57 編集

enumerateの機能を確認するとわかりますが、そのforループは tmp = tmp[tmp[:,0] == a] tmp = tmp[tmp[:,1] == b] tmp = tmp[tmp[:,2] == c] tmp = tmp[tmp[:,3] == d] と4行書いたのと等価です。
O.K.

2018/06/11 12:08

それはわかっていました。 tmpという変数に代入しているtmp[tmp[:,0] == a]は何ですか? [ ]の中に等式があるのを見たことがないのですが...
mkgrei

2018/06/11 14:01

よく見たらこの速すぎるテストケースは…… まあランダムでも2倍以上速いんですけどね。
hayataka2049

2018/06/11 14:26 編集

あ、確かにこれだと1万回+1回+1回+1回の比較ですから、ちょっとずるかったですね・・・ 現実的な速度は毎回どれだけ削れていくか次第です
guest

0

python

1import numpy as np 2 3a = np.random.randint(2, size=(50, 3)) 4 5idx = (a[:, :2]==np.array([0,1])).all(axis=-1) 6 7print(a[idx, -1])

投稿2018/06/11 10:26

mkgrei

総合スコア8560

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

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

O.K.

2018/06/11 10:45

回答ありがとうございます。 二行目以降が何をしているのかわからないのですが、解説していただけませんか?
mkgrei

2018/06/11 11:06

0か1の50×3の配列を先に作っています。 これはご質問されているものの縮小版です。 1番目と2番目の要素が特定の数字の場合、3番目の要素を得る、というように読み替えてください。 次にa[:, :2]==np.array([0,1])のところで、aの50×2の部分を取り出して[0,1]と比較します。 それぞれの行において、1番目と2番目が0と1ならTrueになります。 例えば[0,0]なら[True,False]、[1,1]なら[False,True]などになります。 挙動が不明瞭ならprintで書き出してみてください。 これに.all(axis=-1)をすると、それぞれの行で全ての要素がTrueの場合に限りTrueになります。 例えば、[[True,True],[True,False]]なら[True,False]になります。 ここで次元が1つ落ちます。 最後に、numpy.arrayの機能で、配列と同じ長さのbool配列を入れると、Trueの部分だけ取り出すことができることを利用します。 ですので、a[idx, -1]というのはidxがTrueの行の1番最後の要素、今の場合3番目の要素を取り出すということになります。 これらを応用することでご質問されているような要素を高速に抜き出すことができます。
guest

0

何も考えないで自然に書いたら他の人より100倍以上遅いんですけどなんなんですかね

python3

1def f3(a, b, c, d): 2 result = [] 3 c = np.array([1, 2, 3, 4]) 4 for r in A: 5 if np.array_equal(r[0:4], c): 6 result.append(r[4]) 7

指摘お待ちしてまーす

今見たらキモかったから書き直した

python3

1import timeit 2import numpy as np 3 4A = np.random.randint(low=1, high=5, size=(10000, 5)) 5 6 7def fao_fun(A): 8 result = [] 9 t = np.array([1, 2, 3, 4]) 10 for row in A: 11 if np.array_equal(row[0:4], t): 12 result.append(row[4]) 13 14print(timeit.timeit(lambda: fao_fun(A), number=1))

0.10979769402183592

やっぱり他の人の100倍位遅いね
なんでかな

投稿2018/06/11 17:16

編集2018/07/25 17:18
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

最近覚えたmemoryviewで。

python

1import numpy as np 2view = memoryview(np.array([95, 96, 97, 98])) 3view_size = len(view) 4A = np.arange(50000).reshape((10000, 5)) 5 6for row in A: 7 if memoryview(row)[:view_size] == view: 8 print(row[-1])

追記

python

1ans = tuple(v[-1] for v in map(memoryview, A) if v[:view_size] == view) 2print(ans)

追記2:恥ずかしいくらい遅いので本気を出す

慣れないnumpyを使わずに2dのtuple->listにして素直に書いた方が結果自己記録的に速かった。

python

1import numpy as np 2 3t = [95, 96, 97, 98] 4A = tuple(map(list, np.arange(50000).reshape((10000, 5)))) 5tuple(last for *first, last in A if first == t)

投稿2018/06/11 15:38

編集2018/06/11 17:02
YouheiSakurai

総合スコア6142

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

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

YouheiSakurai

2018/06/11 17:11

あぁ、それにしてもnumpy速い。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問