Sponsored Link

カテゴリー別アーカイブ: numpy

(70) numpy.reshapeは浅いコピー

(70) numpy.reshapeは浅いコピー

4行3列の乱数配列aを作成する。

>>> import numpy as np
>>> a = np.random.rand(4,3)
>>> a
array([[ 0.15940847,  0.56564422,  0.82868468],
       [ 0.55344639,  0.55527501,  0.75242168],
       [ 0.43876864,  0.50025427,  0.07168502],
       [ 0.15186   ,  0.00686738,  0.98197383]])

配列aを numpy.reshape で 6行2列に変形する。

>>> b = np.reshape(a, (6,2))
>>> b
array([[ 0.15940847,  0.56564422],
       [ 0.82868468,  0.55344639],
       [ 0.55527501,  0.75242168],
       [ 0.43876864,  0.50025427],
       [ 0.07168502,  0.15186   ],
       [ 0.00686738,  0.98197383]])

配列bの要素の値を書き換える。

>>> b[3,1] = 0
>>> b
array([[ 0.15940847,  0.56564422],
       [ 0.82868468,  0.55344639],
       [ 0.55527501,  0.75242168],
       [ 0.43876864,  0.        ],
       [ 0.07168502,  0.15186   ],
       [ 0.00686738,  0.98197383]])

すると、配列aの要素も書き換わっている!

>>> a
array([[ 0.15940847,  0.56564422,  0.82868468],
       [ 0.55344639,  0.55527501,  0.75242168],
       [ 0.43876864,  0.        ,  0.07168502],
       [ 0.15186   ,  0.00686738,  0.98197383]])

numpy.reshape したものを別のオブジェクトに代入したい場合、numpy.copy を使用する。

>>> a = np.random.rand(4,3)
>>> a
array([[ 0.59587499,  0.33831817,  0.75324048],
       [ 0.67519994,  0.57802629,  0.48760045],
       [ 0.27385989,  0.02654679,  0.46217751],
       [ 0.20590104,  0.31475441,  0.31250744]])
>>> b = a.reshape(6,2).copy()
>>> b
array([[ 0.59587499,  0.33831817],
       [ 0.75324048,  0.67519994],
       [ 0.57802629,  0.48760045],
       [ 0.27385989,  0.02654679],
       [ 0.46217751,  0.20590104],
       [ 0.31475441,  0.31250744]])
>>> b[3,0] = 0
>>> b
array([[ 0.59587499,  0.33831817],
       [ 0.75324048,  0.67519994],
       [ 0.57802629,  0.48760045],
       [ 0.        ,  0.02654679],
       [ 0.46217751,  0.20590104],
       [ 0.31475441,  0.31250744]])
>>> a
array([[ 0.59587499,  0.33831817,  0.75324048],
       [ 0.67519994,  0.57802629,  0.48760045],
       [ 0.27385989,  0.02654679,  0.46217751],
       [ 0.20590104,  0.31475441,  0.31250744]])

こう書いても同じ。

>>> a = np.random.rand(4,3)
>>> a
array([[ 0.59738729,  0.8289699 ,  0.22344194],
       [ 0.86271615,  0.76692546,  0.1131666 ],
       [ 0.61305503,  0.28302821,  0.24619501],
       [ 0.10828006,  0.38060943,  0.46060143]])
>>> b = np.copy(a.reshape(6,2))
>>> b
array([[ 0.59738729,  0.8289699 ],
       [ 0.22344194,  0.86271615],
       [ 0.76692546,  0.1131666 ],
       [ 0.61305503,  0.28302821],
       [ 0.24619501,  0.10828006],
       [ 0.38060943,  0.46060143]])
>>> b[3,0] = 0
>>> b
array([[ 0.59738729,  0.8289699 ],
       [ 0.22344194,  0.86271615],
       [ 0.76692546,  0.1131666 ],
       [ 0.        ,  0.28302821],
       [ 0.24619501,  0.10828006],
       [ 0.38060943,  0.46060143]])
>>> a
array([[ 0.59738729,  0.8289699 ,  0.22344194],
       [ 0.86271615,  0.76692546,  0.1131666 ],
       [ 0.61305503,  0.28302821,  0.24619501],
       [ 0.10828006,  0.38060943,  0.46060143]])

(69) numpy配列の浅いコピー深いコピー

(69) numpy配列の浅いコピー深いコピー

numpy配列を普通に代入した場合、参照が返される。
すなわち、代入して作った新しい変数は、代入元のオブジェクトを指し示しているだけだ。
このため、一方への変更が他方にも反映される。

>>> import numpy as np
>>> a = np.random.randint(1,10,(3,4))
>>> a
array([[8, 1, 4, 5],
       [4, 9, 9, 9],
       [8, 3, 5, 5]])
>>>
>>> b = a
>>> b[2,2] = -1
>>> b
array([[ 8,  1,  4,  5],
       [ 4,  9,  9,  9],
       [ 8,  3, -1,  5]])
>>> a
array([[ 8,  1,  4,  5],
       [ 4,  9,  9,  9],
       [ 8,  3, -1,  5]])

numpy.copy を使用した場合、別オブジェクトが生成される。
こちらの場合、一方のオブジェクトの変更が他方に反映されない。

>>> a = np.random.randint(1,10,(3,4))
>>> a
array([[8, 4, 7, 7],
       [2, 6, 3, 7],
       [9, 8, 2, 5]])
>>>
>>> c = a.copy()
>>> c
array([[8, 4, 7, 7],
       [2, 6, 3, 7],
       [9, 8, 2, 5]])
>>> c[2,2] = -1
>>> c
array([[ 8,  4,  7,  7],
       [ 2,  6,  3,  7],
       [ 9,  8, -1,  5]])
>>> a
array([[8, 4, 7, 7],
       [2, 6, 3, 7],
       [9, 8, 2, 5]])

注意してプログラムを書かないと、データが次々と破壊されて困ることになりそう…


(67) numpyで配列要素の積

(67) numpyで配列要素の積

numpy.prod で配列要素の積を算出できる。
軸指定なしならば全要素を対象、
axis=Nで軸指定すれば任意方向の要素の積を算出できる。

>>> import numpy as np
>>> a = np.random.randint(0,10,(3,2))
>>> a
array([[9, 4],
       [7, 1],
       [3, 5]])
>>>
>>> a.prod()
3780
>>>
>>> a.prod(axis=0)
array([189,  20])
>>>
>>> a.prod(axis=1)
array([36,  7, 15])

(66) numpyで配列の条件検索

(66) numpyで配列の条件検索

以下のような乱数配列aを作成する。

>>> import numpy as np
>>> a = np.random.randint(0,5,10)
>>> a
array([1, 2, 2, 0, 1, 3, 2, 1, 1, 4])

値が3以上の要素を検索する。→ [5]に3, [9]に4が検出された。

>>> b = np.where(a >= 3)
>>> b
(array([5, 9]),)
>>> a[b]
array([3, 4])

非0の要素を検索する。

>>> c = np.nonzero(a)
>>> c
(array([0, 1, 2, 4, 5, 6, 7, 8, 9]),)
>>> a
array([1, 2, 2, 1, 3, 2, 1, 1, 4])

これでも同じこと。

>>> d = np.where(a != 0)
>>> d
(array([0, 1, 2, 4, 5, 6, 7, 8, 9]),)
>>> a[d]
array([1, 2, 2, 1, 3, 2, 1, 1, 4])

(65) numpyで値が非0の配列要素をカウント

(65) numpyで値が非0の配列要素をカウント

numpy.count_nonzero で値が非0の配列要素数をカウントできる。

>>> import numpy as np
>>> a = np.random.rand(10)
>>> a
array([ 0.35002505,  0.54780005,  0.89527122,  0.64347181,  0.51200932,
        0.11512311,  0.73636012,  0.30606429,  0.57073214,  0.06892677])
>>> b = (a > 0.5) * 1
>>> b
array([0, 1, 1, 1, 1, 0, 1, 0, 1, 0])
>>> np.count_nonzero(b)
6

条件検索で非0の要素のリストを取得し、その要素数をカウントする方法でもよい。

>>> len(np.where(b!=0)[0])
>>> 6

(64) numpyで配列要素をフリップ

(64) numpyで配列要素をフリップ

以下のような乱数配列aを作成する。

>>> import numpy as np
>>> a = np.random.randint(0,10,10)
>>> a
array([9, 0, 1, 8, 0, 4, 6, 5, 5, 4])

配列aの要素の順序を反転してみる。
最終要素[-1]から-1ずつインデックスをずらすことにより実現する。

>>> b = a[-1::-1]
>>> b
array([4, 5, 5, 6, 4, 0, 8, 1, 0, 9])

(63) numpyでソート後配列のインデックスを取得

(63) numpyでソート後配列のインデックスを取得

以下のような乱数配列aを作る。

>>> import numpy as np
>>> a = np.random.rand(10)
>>> a
array([ 0.4556755 ,  0.82176872,  0.49312231,  0.17689834,  0.96413341,
        0.41666999,  0.91981665,  0.26402886,  0.67935056,  0.80891284])

配列要素をソートしたい場合、numpy.sort を使えばよい。

>>> b = np.sort(a)
>>> b
array([ 0.17689834,  0.26402886,  0.41666999,  0.4556755 ,  0.49312231,
        0.67935056,  0.80891284,  0.82176872,  0.91981665,  0.96413341])

降順にしたい場合はソート後の配列をフリップする。

>>> c = b[-1::-1]
>>> c
array([ 0.96413341,  0.91981665,  0.82176872,  0.80891284,  0.67935056,
        0.49312231,  0.4556755 ,  0.41666999,  0.26402886,  0.17689834])

本題の ソート後の配列要素インデックスを得るには? numpy.argsort を使う。

>>> x = np.argsort(a)
>>> x
array([3, 7, 5, 0, 2, 8, 9, 1, 6, 4])

得られたインデックスを使用して、配列要素のソートもできる。

>>> a[x]
array([ 0.17689834,  0.26402886,  0.41666999,  0.4556755 ,  0.49312231,
        0.67935056,  0.80891284,  0.82176872,  0.91981665,  0.96413341])
>>> b - a[x]
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

MATLABもそうだけど、これができるのがとっても便利。


(61) numpy配列を書き換え禁止にする

(61) numpy配列を書き換え禁止にする

5行3列の0行列aを作成し、[1,2]の要素の値を3に書き換える。

>>> import numpy as np
>>> a = np.zeros((5,3))
>>> a
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
>>> a[1,2]=3
>>> a
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  3.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

この配列aに read only 属性を付与する。

>>> a.flags.writeable = False
>>> a.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : False
  ALIGNED : True
  UPDATEIFCOPY : False

すると、値を変更できなくなる。

>>> a[1,2]=9
Traceback (most recent call last):
  File "", line 1, in 
ValueError: assignment destination is read-only

read only属性を外すと、書き込みができるようになる。

>>> a.flags.writeable = True
>>> a.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
>>> a[1,2]=9
>>> a
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  9.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

(60) numpyで配列の等価・不等価を判定

(60) numpyで配列の等価・不等価を判定

numpy.allclose で配列の等価、不等価を判定できる。

以下のような3行3列の配列を作成する。不等価なペアが作成できた。

>>> import numpy as np
>>> a = np.random.randint(0,10,(3,3))
>>> a
array([[4, 9, 7],
       [2, 1, 0],
       [3, 6, 6]])
>>> b = np.random.randint(0,10,(3,3))
>>> b
array([[0, 3, 1],
       [3, 3, 2],
       [0, 2, 1]])

これを等価判定する。結果は当然不等価 False である。

>>> np.allclose(a, b)
False

等価の場合は True が返る。

>>> a
array([[4, 9, 7],
       [2, 1, 0],
       [3, 6, 6]])
>>> c = a
>>> c
array([[4, 9, 7],
       [2, 1, 0],
       [3, 6, 6]])
>>> np.allclose(a, c)
True

(59) numpyでsort

(59) numpyでsort

5行3列の乱数配列aを作成する。

>>> import numpy as np
>>> a = np.random.rand(5,3)
>>> a
array([[ 0.55096361,  0.12996364,  0.37222312],
       [ 0.74124504,  0.37193397,  0.13887862],
       [ 0.41474143,  0.23832064,  0.9245167 ],
       [ 0.41874493,  0.23164232,  0.10248007],
       [ 0.62351702,  0.2568594 ,  0.86498964]])

aを列方向(axis=1)でソートした配列bを作成する。

>>> b = np.sort(a, axis=1)
>>> b
array([[ 0.12996364,  0.37222312,  0.55096361],
       [ 0.13887862,  0.37193397,  0.74124504],
       [ 0.23832064,  0.41474143,  0.9245167 ],
       [ 0.10248007,  0.23164232,  0.41874493],
       [ 0.2568594 ,  0.62351702,  0.86498964]])

引数axisを指定しない場合、列方向のソートになるようだ。

>>> c = np.sort(a)
>>> c
array([[ 0.12996364,  0.37222312,  0.55096361],
       [ 0.13887862,  0.37193397,  0.74124504],
       [ 0.23832064,  0.41474143,  0.9245167 ],
       [ 0.10248007,  0.23164232,  0.41874493],
       [ 0.2568594 ,  0.62351702,  0.86498964]])
>>> b-c
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])

aを行方向(axis=0)でソートした配列dを作成する。

>>> d = np.sort(a, axis=0)
>>> d
array([[ 0.41474143,  0.12996364,  0.10248007],
       [ 0.41874493,  0.23164232,  0.13887862],
       [ 0.55096361,  0.23832064,  0.37222312],
       [ 0.62351702,  0.2568594 ,  0.86498964],
       [ 0.74124504,  0.37193397,  0.9245167 ]])

配列オブジェクトのメソッドとして実行することもできる。

>>> a.sort(axis=0)
>>> d-a
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])