numpy.unique – 既存の配列から要素の重複をなくした配列を生成

numpy.uniqueは重複する値がない新しい配列を生成する関数です。さらに、それに加えて以下の3つを要素とする配列を取得することもできます。

  • 重複あり配列を重複なし配列として更新するためのインダイス
  • 重複なし配列から元の重複あり配列を復元するためのインダイス
  • 重複あり配列でのそれぞれの要素の出現回数

ここでは実際のコードで、これら全てを見ていきます。

目次

1. numpy.uniqueの使い方

それでは、まずはnumpy.uniqueの書き方から確認しましょう。

numpy.unique

np.unique()の書き方:

numpy.unique(arr, return_index=False, return_inverse=False, return_counts=False, axis=None)

パラメーター:

引数   解説
arr  array_like  配列を渡します。axisが指定されていない場合は、1次元配列化します。
return_index(optional)  bool   
これをTrueにすると、重複なし配列とともに、重複なし配列の値のインデックス(指定の軸に従う。axis=Noneの場合は1次元配列化した場合のインデックス)を要素とする配列を返します。このインダイスを使うと、元の重複あり配列を重複なし配列に上書きすることができます。
return_inverse(optional) bool これをTrueにすると、重複なし配列とともに、重複あり配列の値のインデックス(指定の軸に従う。axis=Noneの場合は1次元配列化した場合のインデックス)を要素とする配列を返します。このインダイスを使うと、重複なし配列から元の重複あり配列を復元することができます。
return_counts(optional) boolこれをTrueすると、重複なし配列とともに、それぞれの要素の元の配列における出現回数を要素とする配列を返します。
axis(optional) int or None関数を実行する軸を指定します。None(デフォルト値)では、配列は1次元化されます。

戻り値: 

unique: ndarray: 重複なし配列を戻します。
unique_indeices : ndarray(optional): 元の配列のそれぞれの値の最初のインデックスを要素とする配列を戻します。 
unique_inverse : ndarray(optional): 重複なし配列から、元の重複あり配列を復元するためのインデックスを要素とする配列を戻します。
unique_counts : ndarray(optional): 元の配列における、それぞれの要素の出現回数を要素とする配列を戻します。

一緒に確認したい関数:

  • numpy.lib.arraysetops

それでは、コードを見ながら使い方を確認していきましょう。

1.1. 重複する値のない配列を生成

numpy.uniqueに要素の値の重複がある配列を渡せば、重複のない配列を新しく生成します。

まず、以下のコードで重複する値がある配列を生成します。

In [1]:
'''  np.unique()で値の重複のない配列を生成  '''
import numpy as np
#  重複する値が存在する1次元配列を生成
arr = np.array([1, 1, 2, 3, 4, 5, 5, 5, 5, 5])
arr
Out[1]:
array([1, 1, 2, 3, 4, 5, 5, 5, 5, 5])

これをnumpy.uniqueに渡すと、値の重複のない配列を生成してくれます。

In [2]:
np.unique(arr)
Out[2]:
array([1, 2, 3, 4, 5])

多次元配列を渡した場合も、デフォルトでは新しい配列を1次元化して生成します。以下のコードは2次元配列の場合ですが、3次元配列でも4次元配列でも1次元配列化します。

In [3]:
'''  多次元配列を渡すと1次元配列として戻す  '''
#  2次元配列を生成
arr = np.array([[0, 1, 1], [2, 0, 0], [2, 3, 4]])
print('arr:\n', arr)
#   値の重複なしの配列を1次元配列として生成
uni = np.unique(arr)
print('uni:\n', uni)
arr:
 [[0 1 1]
 [2 0 0]
 [2 3 4]]
uni:
 [0 1 2 3 4]

1.2. 値が重複する軸をなくす(axis)

2次元配列以上の多次元配列で、オプション引数「axis=」を使うと、要素が全く同じ行や列をなくすことができます。

以下のコードは2次元配列の場合です。

2次元配列はaxis=0は「行」で、axis=1は「列」です。そのため、axis=0を指定すると値が重複する行をなくします。axis=1を指定すると値が重複する列をなくします。

In [4]:
'''  2次元配列でaxisを指定  '''
#  2次元配列を生成
arr = np.array([[0, 1, 1], [0, 1, 1], [2, 1, 1], [3, 1, 1]])
print('arr:\n', arr, '\n')

#   axis=0(要素が重複する行をなくす)
uni = np.unique(arr, axis=0)
print('axis=0:\n', uni, '\n')

#   axis=1(要素が重複する列をなくす))
uni = np.unique(arr, axis=1)
print('axis=1:\n', uni, '\n')
arr:
 [[0 1 1]
 [0 1 1]
 [2 1 1]
 [3 1 1]] 

axis=0:
 [[0 1 1]
 [2 1 1]
 [3 1 1]] 

axis=1:
 [[0 1]
 [0 1]
 [2 1]
 [3 1]] 

3次元配列の場合も見てみましょう。

3次元配列ではaxis=0は「奥行き」です。この場合、異なる奥行きで値が完全に重複する場合は、その重複を解消します。axis=1は「行」なので、値が重複する行をなくします。axis=2は「列」なので、値が重複する列をなくします。

In [5]:
'''  3次元配列でaxisを指定  '''
#  2次元配列を生成
arr = np.array([[[0, 1, 1], [0, 1, 1], [2, 1, 1]], [[0, 1, 1], [0, 1, 1], [2, 1, 1]]])
print('arr:\n', arr, '\n')

#   axis=0(要素が重複する奥行きをなくす)
uni = np.unique(arr, axis=0)
print('axis=0:\n', uni, '\n')

#   axis=1(要素が重複する行をなくす))
uni = np.unique(arr, axis=1)
print('axis=1:\n', uni, '\n')

#   axis=2(要素が重複する列をなくす))
uni = np.unique(arr, axis=2)
print('axis=2:\n', uni, '\n')
arr:
 [[[0 1 1]
  [0 1 1]
  [2 1 1]]

 [[0 1 1]
  [0 1 1]
  [2 1 1]]] 

axis=0:
 [[[0 1 1]
  [0 1 1]
  [2 1 1]]] 

axis=1:
 [[[0 1 1]
  [2 1 1]]

 [[0 1 1]
  [2 1 1]]] 

axis=2:
 [[[0 1]
  [0 1]
  [2 1]]

 [[0 1]
  [0 1]
  [2 1]]] 

1.3. 元の重複あり配列を重複なし配列に変換するインダイスを取得(return_index)

オプション引数で「return_index=True」と指定すると、重複なし配列と、値が重複する要素の一番最初のインデックスを取り出したインダイスの配列の2つが格納されたタプルを返します。

このインダイスの配列を使うと、元の重複あり配列を、重複なし配列として更新することができます。

まずは以下のコードをご確認下さい。

In [6]:
'''  return_indexを指定すると、要素のインデックスも返す '''
arr = np.array([1, 2, 1, 3, 4, 5, 3, 1, 6, 4, 7])
#  return_index=Trueで関数を実行
np.unique(arr, return_index=True)
Out[6]:
(array([1, 2, 3, 4, 5, 6, 7]), array([ 0,  1,  3,  4,  5,  8, 10]))

タプルの先頭の配列が重複なし配列で、2つめの配列がインダイスです。

次のように書くと、重複なし配列と、そのインダイス配列を、それぞれ別の変数に代入することができます。

In [7]:
'''  重複をなくした配列と、インダイスの配列を別の変数に代入'''
uni, indices = np.unique(arr, return_index=True)
print('重複をなくした配列: \n', uni)
print('インダイスの配列: \n', indices)
重複をなくした配列: 
 [1 2 3 4 5 6 7]
インダイスの配列: 
 [ 0  1  3  4  5  8 10]

これを用いて、以下のように書くと、元の配列を重複なし配列として上書きすることができますので覚えておきましょう。

In [8]:
'''  インダイスで重複あり配列を重複なし配列として上書きできる  '''
#  元の配列arrを上書き
arr = arr[indices]
arr
Out[8]:
array([1, 2, 3, 4, 5, 6, 7])

1.4. 重複なし配列を重複あり配列に戻すインダイスを取得(return_inverse)

オプション引数で「return_inverse=True」と指定すると、重複なし配列と、元の重複あり配列のインダイスが格納されたタプルを返します。

こちらのインダイスを使うと、重複なし配列を、元の重複あり配列に戻すことができます。

まずは以下のコードをご覧ください。

In [9]:
'''  return_inverseで元の配列を復元するためのインダイスを取得  '''
arr = np.array([1, 2, 1, 3, 4, 5, 3, 1, 6, 4, 7])
#  return_inverse=Trueで関数を実行
np.unique(arr, return_inverse=True)
Out[9]:
(array([1, 2, 3, 4, 5, 6, 7]), array([0, 1, 0, 2, 3, 4, 2, 0, 5, 3, 6]))

このインダイスを使って、重複なし配列を、元の重複あり配列に戻しているのが以下のコードです。

In [10]:
''' return_inverseで元の配列を復元 '''
#  変数uniと変数r_indicesにそれぞれ重複なし配列と、インダイスを代入
uni, r_indices = np.unique(arr, return_inverse=True)
#  重複なし配列
print(uni)
#  return_inverseのインデックス
print(r_indices)
#  重複なし配列から元の重複あり配列を復元
print(uni[r_indices])
[1 2 3 4 5 6 7]
[0 1 0 2 3 4 2 0 5 3 6]
[1 2 1 3 4 5 3 1 6 4 7]

1.5. それぞれの値の出現回数を取得

オプション引数で「return_counts=True」を指定すると、重複なし配列と、元の配列におけるそれぞれの値の出現回数を要素とした配列を格納するタプルを返します。

以下のコードでご確認ください。

In [11]:
'''  return_countsで重複要素の出現回数を取得  '''
arr = np.array([1, 2, 1, 3, 4, 5, 3, 1, 6, 4, 7])
#  return_counts=Trueで関数を実行
uni, counts = np.unique(arr, return_counts=True)
print('重複なし配列: \n', uni)
print('各要素の出現回数: \n', counts)
重複なし配列: 
 [1 2 3 4 5 6 7]
各要素の出現回数: 
 [3 1 2 2 1 1 1]

2. まとめ

以上が、numpy.uniqueの使い方です。



よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

目次
閉じる