2017-07-06 5 views
0

内のすべての単一の要素私は、ランダムなN×m個の要素を持つnumpyのオブジェクトを持っている、と私はまた、二つの数AとB変更にnumpyのオブジェクト

は今、私はこのN * M配列内のすべての要素にアクセスしたいしているにしてすなわち、要素> 0の場合は、この要素をA(つまり要素<-A)に置き換えます。この要素が<の場合は、この要素をB(つまり要素<-B)に置き換えます。

私はこの方法を実装する単純な方法があることを知っています。それはforループを使用してすべての要素にアクセスしていますが、非常に遅いです。

これを実装するために、より多くのファンシーコードを使用できますか?

+0

「numpy.clip」を試してください。 – Divakar

+0

'np.where'を見てください –

答えて

2

場所に値を変更しますブールマスクされた割り当て:

In [493]: arr = np.random.randint(-10,10,(5,7)) 
In [494]: arr 
Out[494]: 
array([[ -5, -6, -7, -1, -8, -8, -10], 
     [ -9, 1, -3, -9, 3, 8, -1], 
     [ 6, -7, 4, 0, -4, 4, -2], 
     [ -3, -10, -2, 7, -4, 2, 2], 
     [ -5, 5, -1, -7, 7, 5, -7]]) 
In [495]: arr[arr>0] = 100 
In [496]: arr[arr<0] = -50 
In [497]: arr 
Out[497]: 
array([[-50, -50, -50, -50, -50, -50, -50], 
     [-50, 100, -50, -50, 100, 100, -50], 
     [100, -50, 100, 0, -50, 100, -50], 
     [-50, -50, -50, 100, -50, 100, 100], 
     [-50, 100, -50, -50, 100, 100, -50]]) 

私はちょうど

python numpy: iterate for different conditions without using a loop

1

IIUC:

narr = np.random.randint(-100,100,(10,5)) 
array([[ 70, -20, 96, 73, -94], 
     [ 42, 35, -55, 56, 54], 
     [ 97, -16, 24, 32, 78], 
     [ 49, 49, -11, -82, 82], 
     [-10, 59, -42, -68, -70], 
     [ 95, 23, 22, 58, -38], 
     [ -2, -64, 27, -33, -95], 
     [ 98, 42, 8, -83, 85], 
     [ 23, 51, -99, -82, -7], 
     [-28, -11, -44, 95, 93]]) 
A = 1000 
B = -999 

使用np.where

np.where(narr > 0, A, np.where(narr < 0, B , narr)) 

出力:

array([[1000, -999, 1000, 1000, -999], 
     [1000, 1000, -999, 1000, 1000], 
     [1000, -999, 1000, 1000, 1000], 
     [1000, 1000, -999, -999, 1000], 
     [-999, 1000, -999, -999, -999], 
     [1000, 1000, 1000, 1000, -999], 
     [-999, -999, 1000, -999, -999], 
     [1000, 1000, 1000, -999, 1000], 
     [1000, 1000, -999, -999, -999], 
     [-999, -999, -999, 1000, 1000]]) 
+0

これは役に立ちます!しかし元の配列narrは変更されていないので、この新しい配列を保持するために新しいメモリを割り当てる必要があります。この変更をその場で行うことはできますか? – dodolong

0

で同様の答えを与えたあなたは、計算の速さに興味を持っていることを述べたので、私はあなたの問題のために、いくつかの異なるアプローチの速度比較ですが作りました。

test.py:

import numpy as np 

A = 100 
B = 50 

def createArray(): 
    array = np.random.randint(-100,100,(500,500)) 
    return array 

def replace(x): 
    return A if x > 0 else B 

def replace_ForLoop(): 
    """Simple for-loop.""" 
    array = createArray() 
    for i in range(array.shape[0]): 
     for j in range(array.shape[1]): 
      array[i][j] = replace(array[i][j]) 

def replace_nditer(): 
    """Use numpy.nditer to iterate over values.""" 
    array = createArray() 
    for elem in np.nditer(array, op_flags=['readwrite']): 
     elem[...] = replace(elem) 

def replace_masks(): 
    """Use boolean masks.""" 
    array = createArray() 
    array[array>0] = A 
    array[array<0] = B 

def replace_vectorize(): 
    """Use numpy.vectorize""" 
    array = createArray() 
    vectorfunc = np.vectorize(replace) 
    array = vectorfunc(array) 

def replace_where(): 
    """Use numpy.where""" 
    array = createArray() 
    array = np.where(array > 0, A, np.where(array < 0, B , array)) 

注:forループのネストされた変種を使用して、np.nditerとブールマスクは最後の二つがいない、インプレース働きます。

タイミング比較です:

> python -mtimeit -s'import test' 'test.replace_ForLoop()'      
10 loops, best of 3: 185 msec per loop 
> python -mtimeit -s'import test' 'test.replace_nditer()' 
10 loops, best of 3: 294 msec per loop 
> python -mtimeit -s'import test' 'test.replace_masks()' 
100 loops, best of 3: 5.8 msec per loop 
> python -mtimeit -s'import test' 'test.replace_vectorize()' 
10 loops, best of 3: 55.3 msec per loop 
> python -mtimeit -s'import test' 'test.replace_where()'  
100 loops, best of 3: 5.42 msec per loop 

ループを使用するには、確かに非常に遅いです。 numpy.nditerはさらに遅く、私が驚いたのは、docがefficient multi-dimensional iterator object to iterate over arraysと呼んでいるからです。 numpy.vectorizeis essentially a for-loopでもありますが、これまでの実装と同じくらい速い速度で管理します。 Scott Bostonが提案したnp.whereの亜種は、hpauljの回答に従ってブールマスクを使用するよりもわずかに高速です。しかし、それはインプレースを変更しないので、より多くのメモリを必要とします。

関連する問題