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

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

ただいまの
回答率

90.62%

  • Python

    7525questions

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

  • NumPy

    420questions

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

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

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 479

O.K.

score 22

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

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

for i in array:
    if i[0] == 1 and i[1] == 2 and i[2] == 3 and i[3] == 4:
        print(i[4])
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+5

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

import timeit
import numpy as np

A = np.arange(50000).reshape((10000, 5))

def f0(a,b,c,d):
    """質問文の方式
    """
    lst = []
    for i in A:
        if i[0] == 1 and i[1] == 2 and i[2] == 3 and i[3] == 4:
            lst.append(i[4])
    # print(lst)
    lst

def f1(a,b,c,d):
    """私が考えた方式。一列ずつ見て、削っていきます
    こうすると比較の回数がケチれて(本質的には短絡評価と同じことをしています)速いはずです
    """
    tmp = A
    for i, eqv in enumerate([a,b,c,d]):
        tmp = tmp[tmp[:,i] == eqv]

    # print(tmp[:,-1])
    tmp[:,-1]  # 計測時にprintしたくなかったので

def f2(a,b,c,d):
    """mkgreiさんの方式
    """
    idx = (A[:, :4]==np.array([a,b,c,d])).all(axis=-1)
    # print(A[idx, -1])
    A[idx, -1]  # 計測時にprintしたくなかったので

print(timeit.timeit(lambda : f0(0,1,2,3), number=1000))
print(timeit.timeit(lambda : f1(0,1,2,3), number=1000))
print(timeit.timeit(lambda : f2(0,1,2,3), number=1000))
"""
私の環境だと、
3.3318773460000557
0.06133379499988223
0.27946032499994544
くらい
"""

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/11 20:12

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

    キャンセル

  • 2018/06/11 20:13

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

    キャンセル

  • 2018/06/11 20:53

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

    キャンセル

  • 2018/06/11 20:57 編集

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

    キャンセル

  • 2018/06/11 21:08

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

    キャンセル

  • 2018/06/11 21:13

    numpy配列とスカラーの比較をすると、booleanの配列になります。
    booleanの配列をインデックスに入れると、Trueのところだけ取り出せます。
    https://docs.scipy.org/doc/numpy-1.13.0/user/basics.indexing.html#boolean-or-mask-index-arrays

    キャンセル

  • 2018/06/11 23:01

    よく見たらこの速すぎるテストケースは……

    まあランダムでも2倍以上速いんですけどね。

    キャンセル

  • 2018/06/11 23:25 編集

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

    キャンセル

+1

import numpy as np 

a = np.random.randint(2, size=(50, 3))

idx = (a[:, :2]==np.array([0,1])).all(axis=-1)

print(a[idx, -1])

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/11 19:45

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

    キャンセル

  • 2018/06/11 20: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番目の要素を取り出すということになります。

    これらを応用することでご質問されているような要素を高速に抜き出すことができます。

    キャンセル

  • 2018/06/11 20:11

    対案投げてみました

    キャンセル

0

最近覚えたmemoryviewで。

import numpy as np
view = memoryview(np.array([95, 96, 97, 98]))
view_size = len(view)
A = np.arange(50000).reshape((10000, 5))

for row in A:
    if memoryview(row)[:view_size] == view:
        print(row[-1])

 追記

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

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

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

import numpy as np

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/12 02:11

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

    キャンセル

-3

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

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


指摘お待ちしてまーす

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

import timeit
import numpy as np

A = np.random.randint(low=1, high=5, size=(10000, 5))


def fao_fun(A):
    result = []
    t = np.array([1, 2, 3, 4])
    for row in A:
        if np.array_equal(row[0:4], t):
            result.append(row[4])

print(timeit.timeit(lambda: fao_fun(A), number=1))


0.10979769402183592

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    Kerasで学習済みモデルを初期化できない

    kerasを使って学習済みモデルの評価をしようとしています。しかし、重みを設定するとタイトルのようなエラーが出てしまいました。フィルタ数、つまり最初のnOutoutPlaneは32

  • 解決済

    ソート結果が正しくない

    前提・実現したいこと csvファイルdata1.csvおよびそれと同じフォーマットのcsvファイルdata2.csv, csvファイルdata3.csvのそれぞれに対して,温度(

  • 受付中

    関数の実装、matmulを利用

    追記:print(np.matmul(A, x)) まではできたのですが、それ以降はどのように書けば良いでしょうか?

  • 解決済

    outputがでず、困っています。

    下記の質問で、outputを出そうとするとエラーになってしまいます。解決方法をご存知でしょうか。 ifname=="main":の後に、エラーがでてきます。。 A user

  • 解決済

    UnboundLocalError: local variable 'count' referenc...

    UnboundLocalError: local variable 'count' referenced before assignmentのエラーの原因 がわかりません。 #

  • 解決済

    python 文字列を判定する方法

    何らかのstr型が連続して格納されている配列(例['100'],['.'],['abc'])の各要素を判定し、数値ならint型に変換後次要素の判定に移る、数値ではないのであればfa

  • 解決済

    Python,numpyについてです

    a = np.ones((20, 2)) * 10 以上の様に配列が作られ、それに対して、以下の様にshapeを表示します。 print(a.shape) すると実行結果は(2

  • 解決済

    pythonアルゴリズムの質問

    pythonについて、 def bowling(a): score = 0 for i in range(0,len(a)-1): score += a[i] if a[

同じタグがついた質問を見る

  • Python

    7525questions

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

  • NumPy

    420questions

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