별의 공부 블로그 🧑🏻‍💻
728x90
728x170

구조화된 배열

  • 구조화된 배열(Structured Array) ndarrays 를 의미한다.
    • ndarrays 데이터 타입은 시퀀스로 조직화된 단순한 데이터 타입인 필드를 모은 것
      • 필드 : 구조화된 데이터 타입의 각 서브 타입에서 이름(string), 데이터 타입(dtype) 및 제목(title)

 

예제
>>> arr = np.array([('jin', 25, 67), ('suho', 18, 77)], dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
>>> arr
array([('jin', 25, 67.), ('suho', 18, 77.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])
  • arr은 필드가 3개인 데이터 타입 구조이며 1차원 배열이다.
    • 첫 번째 필드는 'name'이란 이름을 갖는 길이 10 이하의 문자열이다.
    • 두 번째 필드는 'age'라는 이름을 갖는 32비트 정수이다.
    • 세 번째 필드는 'weight'라는 이름의 32비트 실수이다.

 

  • 구조화 배열 데이터 필드로의 접근 및 변경
>>> arr[1]
('suho', 18, 77.)
>>> arr['age'] = 20
>>> arr
array([('jin', 20, 67.), ('suho', 20, 77.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

 

구조화된 데이터 타입

  • 구조화된 데이터 타입(Structured Datatype)
    • 요소 크기가 바이트 단위인 시퀀스
    • 필드를 모아 놓은 것이라 할 수 있다.
    • 각 필드 구조 안에는 이름, 데이터 타입  오프셋을 포함한다.
      • 오프셋
        • 필드 시작점에서의 위치를 바이트로 나타내는 속성
        • 필드의 오프셋은 임의적이며 중첩될 수 있다.
        • 보통 넘파이에 의해 자동으로 결정되지만, 직접 입력하여 설정할 수도 있다.

 

구조화된 데이터 타입 생성

  • numpy.dtype() 함수를 사용해 다음 4가지 형태로 구조화된 데이터 타입을 생성할 수 있다.

 

① 1개 필드를 1개의 튜플로 구성하는 튜플의 리스트 형태
  • 각 튜플은 (필드 이름, 데이터 타입, shape) 구조를 가진다.
    • 필드 이름 : 문자열(타이틀을 사용할 경우 튜플)
    • 데이터 타입 : 데이터 타입으로 변경될 수 있는 객체
    • shape : 서브 배열 shape를 나타내는 정수들의 튜플
>>> np.dtype([('a', 'f4'), ('b', np.float32), ('c', 'f4', (2, 2))])
dtype([('a', '<f4'), ('b', '<f4'), ('c', '<f4', (2, 2))])

 

  • 필드 이름이 빈 문자열인(' ')이라면 기본 이름인 f#의 형태로 부여된다.
    • # : 필드의 정수 인덱스이며, 왼쪽부터 0, 1, 2 순으로 번호가 부여됨.
>>> np.dtype([('a', 'f4'), ('', 'i4'), ('c', 'i8')])
dtype([('a', '<f4'), ('f1', '<i4'), ('c', '<i8')])

 

② 콤마로 구분하는 dtype 문자열 형태
  • 필드의 바이트 오프셋 itemsize는 자동으로 결정된다.
  • 이때 필드 이름은 기본 이름인 f0, f1 등으로 부여된다.
>>> np.dtype('i8, f4, S3')
dtype([('f0', '<i8'), ('f1', '<f4'), ('f2', 'S3')])

>>> np.dtype('3int8, float32, (2, 3)float64')
dtype([('f0', 'i1', (3,)), ('f1', '<f4'), ('f2', '<f8', (2, 3))])

 

③ 필드 매개 변수 배열의 딕셔너리 형태
  • 딕셔너리는 데이터 구조의 필드 바이트 오프셋 itemsize를 조정할 수 있어 가장 유연한 형태이다.
  • 딕셔너리는 2개의 필수 키인 names, formats 4개의 옵션 키 offsets, itemsize, aligned 그리고 titles를 가진다.
    • names formats 키의 값은 같은 길이인 각 필드 이름의 리스트다.
      • 이 리스트는 데이터 타입 규격의 리스트여야 한다.
    • offsets를 입력하지 않으면 자동으로 결정된다.
    • 옵션 키 itemsize 값은 모든 필들르 충분히 포함할 수 있는 데이터 타입을 총 바이트 크기로 표시한 정수여야 한다.
>>> np.dtype({'names': ['col1', 'col2'], 'formats': ['i4', 'f4']})
dtype([('col1', '<i4'), ('col2', '<f4')])

>>> np.dtype({'names': ['col1', 'col2'], 'formats': ['i4', 'f4'], 'offsets': [0, 4], 'itemsize': 12})
dtype({'names': ['col1', 'col2'], 'formats': ['<i4', '<f4'], 'offsets': [0, 4], 'itemsize': 12})

 

④ 필드 이름이 딕셔너리인 형태
  • 딕셔너리의 키는 필드 이름이고 같은 타입과 오프셋으로 구성된 튜플이다.
>>> np.dtype({'col1': ('i1', 0), 'col2': ('f4', 1)})
dtype([('col1', 'i1'), ('col2', '<f4')])
  • 구조화된 dtype에서 필드의 순서는 의미가 있다.
    • 그러나 파이썬 딕셔너리가 순서를 고려하지 않으므로 앞과 같은 형태를 사용하는 것은 권장되지 않는다.

 

구조화된 데이터 타입 조작 및 표시

  • dtype 객체의 names 속성을 이용하면 구조화된 데이터 타입에서 필드 이름의 튜플을 구할 수 있다.
>>> c = np.dtype([('a', 'i8'), ('b', 'f4')])
>>> c.names
('a', 'b')

 

  • names 속성에 같은 길이의 문자열 시퀀스를 할당하면 필드 이름을 변경할 수 있다.
  • dtype 객체는 딕셔너리 같은 속성 필드를 포함한다.
    • 이 필드들의 키는 필드 이름이고, 값은 각 필드의 데이터 파일과 바이트 오프셋을 포함하는 튜플이다.
>>> c.fields
mappingproxy({'a': (dtype('int64'), 0), 'b': (dtype('float32'), 8)})

 

  • 구조화되지 않은 배열에서 names fields 속성은 None과 같다.

 

자동 바이트 오프셋 및 정렬

  • numpy.dtype의 키워드 인수
    • align=True 를 입력할 경우
      • 구조화된 데이터 타입의 필드 바이트 오프셋과 총 itemsize 자동으로 결정한다.
    • align=False 를 입력할 경우
      • 넘파이는 이전 필드가 끝났던 바이트 오프셋에서 각 필드가 시작하도록 필드를 함께 팩(Pack)한다.
      • 이때 필드는 메모리에서 인접해 있다.
>>> def print_offsets(d):
...     print("offsets:", [d.fields[name][1] for name in d.names])
...     print("itemsize:", d.itemsize)
...

>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2'))
offsets: [0, 1, 2, 6, 7, 15]
itemsize: 17
  • itemsize는 17 바이트이다.
  • 오프셋은 정수값이며, 기준 바이트인 0에서 떨어져 있는 바이트 수다.
    • 요소의 데이터 타입인 u1, u1, i4, u1, i8, u2는 메모리 인근에서 차례대로 0, 1, 2, 6, 7, 15 바이트 간격으로 배치되었다.

 

>>> d = np.dtype('u1, u1, i4, u1, i8, u2')
>>> d
dtype([('f0', 'u1'), ('f1', 'u1'), ('f2', '<i4'), ('f3', 'u1'), ('f4', '<i8'), ('f5', '<u2')])

>>> d.itemsize
17

>>> d.fields
mappingproxy({'f0': (dtype('uint8'), 0), 'f1': (dtype('uint8'), 1), 'f2': (dtype('int32'), 2), 'f3': (dtype('uint8'), 6), 'f4': (dtype('int64'), 7), 'f5': (dtype('uint16'), 15)})

>>> d.names
('f0', 'f1', 'f2', 'f3', 'f4', 'f5')

>>> d.fields['f0']
(dtype('uint8'), 0)

>>> d.fields['f0'][1]
0

 

  • 많은 C 컴파일러 C struct에 패드를 대는 것과 같이, 넘파이에서 align=True를 설정하면 구조에 패드를 댄다.
    • "패드를 댄다."
      • 예) 64비트 운영 체제에서 처리되는 단위 데이터의 특정 필드가 비어 있어 64비트에 맞지 않으면 64비트에 맞추기 위해 모자라는 비트를 덧붙이는 것
      • 이 작업을 하지 않으면 동기화되지 않아 오류가 발생하거나 속도가 저하될 수 있다.
  • 구조를 정렬하여 데이터 타입 크기가 증가하면 성능을 향상시키는 경우도 있다.
    • 각 필드 바이트 오프셋이 필드 정렬의 배수가 되도록 필드 사이에 삽입되는 패딩 바이트(Padding Byte)
    • itemsize 가 가장 큰 필드 정렬의 배수가 되도록 더해진 뒷부분의 패드를 가진다.
print_offsets(np.dtype('u1, u1, i4, u1, i8, u2', align=True))
offsets: [0, 1, 4, 8, 16, 24]
itemsize: 32

 

  • 딕셔너리 기반 데이터 타입에서는 offsets 키를 사용해 오프셋을 확인한다.
  • align=True 를 설정하면 각 필드의 오프셋이 필드 크기의 배수이고, itemsize 가 가장 큰 필드 크기의 배수라는 것을 확인할 수 있다.
    • 이러한 구조가 아니면 예외가 발생한다.

 

필드 제목

  • 필드는 필드 이름 외에도 관련 제목, 추가 설명을 위해 사용하는 대체 이름 또는 필드에 대한 별칭을 가질 수 있다.
  • 제목은 필드 이름과 같이 배열을 인덱싱하는 데 사용할 수 있다.
  • 튜플 리스트형의 데이터 타입에서 제목을 추가할 때, 필드 이름은 하나의 문자열 대신 필드 제목과 필드 이름, 즉 2개 문자열인 튜플로 입력할 수 있다.
  • 필드 속성에 접근하면 mappingproxy의 인수가 데이터 타입, 오프셋, 제목임을 확인할 수 있다.
>>> x = np.dtype([(('my title', 'name'), 'f4')])
>>> x.fields
mappingproxy({'name': (dtype('float32'), 0, 'my title'), 'my title': (dtype('float32'), 0, 'my title')})

>>> x.names
('name',)

 

  • 딕셔너리 기반 형태를 사용할 때 titles 키를 이용해 필드 제목을 입력할 수 있다.
  • 또한 (datatype, offset, title)처럼 3개 요소로 이루어진 튜플을 이용해 제목을 입력할 수 있다.
>>> np.dtype({'name': ('i4', 0, 'my title')})
dtype([(('my title', 'name'), '<i4')])

 

구조화된 배열 인덱싱 및 할당

  • 구조화된 배열에 값을 할당하려면 파이썬 튜플, 스칼라 값 또는 다른 구조화된 배열을 이용하는 등 몇 가지 방법을 사용할 수 있다.
    • 값을 할당하는 것은 동적으로 할당한다는 의미이며, 객체 지향 프로그래밍 언어에서 보편적으로 사용하는 개념이다.

 

파이썬 고유 타입인 튜플로 할당

  • 구조화된 배열에 파이썬 튜플을 이용하여 값을 할당할 수 있다.
  • 입력값은 배열에서 필드의 요소 수와 같은 길이의 튜플이어야 하며, 길이가 다르면 오류가 발생한다.

 

>>> a = np.array([(1, 2, 3), (4, 5, 6)], dtype='i8, f4, f8')
>>> a[1] = (7, 8, 9)
>>> a
array([(1, 2., 3.), (7, 8., 9.)],
      dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '<f8')])

 

스칼라 값으로 할당

  • 구조화된 요소에 스칼라를 할당하면 모든 필드에 할당된다.
  • 스칼라가 구조화된 배열에 할당되거나 구조화되지 않은 배열이 구조화된 배열로 할당될 때 이러한 결과가 발생한다.
>>> a = np.zeros(2, dtype='i8, f4, ?, S1')
>>> a
array([(0, 0., False, b''), (0, 0., False, b'')],                         // b : bytes 리터럴
      dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])
      
>>> a[:] = 7
>>> a
array([(7, 7.,  True, b'7'), (7, 7.,  True, b'7')],
      dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])
      
>>> a[:] = np.arange(2)
>>> a
array([(0, 0., False, b'0'), (1, 1.,  True, b'1')],
      dtype=[('f0', '<i8'), ('f1', '<f4'), ('f2', '?'), ('f3', 'S1')])

 

다른 구조화된 배열로 할당

  • 2개의 구조화된 배열 사이의 할당은 할당하는 쪽의 요소가 튜플로 변환된 다음, 받는 쪽에 할당되는 것처럼 발생한다.
    • 예를 들어, 할당하는 배열의 첫 번째 필드는 받는 배열의 첫 번째 필드에 할당된다.
    • 두 번째, 세 번째 필드 역시 이름과 관계없이 이러한 방식으로 할당된다.
  • 구조화된 배열의 필드 개수가 각각 다르면 서로 할당될 수 없다.
>>> a = np.zeros(3, dtype=([('a', 'i8'), ('b', 'f4'), ('c', 'S3')]))
>>> b = np.ones(3, dtype=[('x', 'f4'), ('y', 'S3'), ('z', 'O')])
>>> b[:] = a
>>> b
array([(0., b'0.0', b''), (0., b'0.0', b''), (0., b'0.0', b'')],
      dtype=[('x', '<f4'), ('y', 'S3'), ('z', 'O')])

 

 

인덱싱과 슬라이싱

  • 표준 파이썬 구문인 x[obj]를 사용하면 배열 객체인 ndarrays 인덱싱(Indexing) 할 수 있다.
    • x : 배열
    • obj : 선택하려는 인덱스

 

기본 인덱싱 구문

i : j : k

- i : 시작 인덱스
- j : 종료 인덱스
- k : 간격(Step), 표기하지 않으면 1로 간주됨.
  • 배열 객체 내에서 첫 번째 요소는 인덱스 0, 다음 요소들은 순서대로 1씩 추가된다.
    • i는 시작 인덱스, j - 1은 종료 인덱스
구문 유형 설명
arr[i:] 배열의 인덱스 i부터 끝까지의 요소 선택
arr[i:j:k] - i : 시작 인덱스, j - 1: 종료 인덱스, k : 간격(옵션)
- 시작하는 인덱스 i부터 간격 k를 더하여 인덱스 j - 1까지의 요소를 선택
arr[:], arr[::] 배열의 모든 요소를 선택
arr[::2] 배열의 첫 번째 인덱스인 0부터 끝 요소까지 선택하되, 간격 2씩 더해서 마지막 요소 범위까지 선택
arr[-1] 배열의 마지막 요소
arr[:-1] - :를 중심으로 왼쪽은 공백이므로 첫 번째 요소이고, 오른쪽은 -1, 즉 j - 1이기 때문에 -2이다.
- 첫 번째부터 끝에서 두 번째까지의 요소를 선택
arr[-2:] 배열의 끝에서 두 번째부터 배열의 마지막 요소까지 선택
arr[:-2] 배열의 처음부터 끝에서 세 번째까지의 요소를 선택
arr[::-1] 배열의 모든 요소를 마지막 요소부터 첫 번째 요소까지 역순으로 선택
arr[1::-1] 인덱스 1부터 마지막 요소를 선택하되, 간격이 -1로 역순이 되므로 두 번째 요소와 첫 번째 요소를 차례로 선택
arr[-3::-1] 배열의 끝에서 세 번째 요소부터 마지막 요소까지를 선택하되, 간격이 -1이므로 역순으로 선택

 

배열 객체 요소 선택

  • 파이썬 리스트에서 요소를 선택하는 것과 같이 다차원 배열에서 요소를 간단한게 선택할 수 있다.
>>> arr1 = np.arange(10)
>>> arr1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

>>> arr1[1]
1

 

  • 2차원 배열 객체에서 요소를 선택하려면 인수 2개를 사용한다.
    • 첫 번째 인수 : 
    • 두 번째 인수 : 
>>> arr2 = np.arange(9).reshape(3, 3)
>>> arr2
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
       
>>> arr2[2, 1]
7

 

  • 3차원 배열 객체에서는 인수 3개를 사용하여 요소를 선택한다.
    • 첫 번째 인수 : 
    • 두 번째 인수 : 
    • 세 번째 인수 : 
>>> arr3 = np.reshape(np.arange(24), (2, 3, 4))
>>> arr3
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
        
>>> arr3[1, 1, 2]
18

>>> arr3[1][2][3]
23

 

기본 인덱싱과 슬라이싱

  • [start:stop:step] 으로 구성된 slice 객체, 정수, slice 객체와 정수의 튜플 등을 이용해 기본 슬라이싱(Slicing)을 실행할 수 있다.
  • 정수 인덱스를 처리하는 가장 간단한 방법은 배열 스칼라를 반환하는 것이다.
  • 기본 인덱싱 처리로 생성되는 모든 배열은 항상 원본 배열의 뷰(View)이다.
    • 뷰(View) : 원본 배열 객체를 인덱싱하여 자른 후 생성된 배열

 

배열 샘플 생성
>>> arr1 = np.arange(10)
>>> arr1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> arr2 = np.arange(9).reshape(3, 3)
>>> arr2
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> arr3 = np.reshape(np.arange(24), (2, 3, 4))
>>> arr3
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
arr1
0 1 2 3 4 5 6 7 8 9
-10 -9 -8 -7 -6 -5 -4 -3 -2 -1
0 1 2 3 4 5 6 7 8 9

 

arr2
0 1 2
3 4 5
6 7 8

 

arr3
0 1 2 3   12 13 14 15
4 5 6 7 16 17 18 19
8 9 10 11 20 21 22 23

 

예제
>>> arr1[1]
1

>>> arr1[:6]
array([0, 1, 2, 3, 4, 5])

>>> arr1[0:5]
array([0, 1, 2, 3, 4])

>>> arr1[::2]
array([0, 2, 4, 6, 8])

>>> arr1[1::2]
array([1, 3, 5, 7, 9])

>>> arr1[1:7:2]
array([1, 3, 5])

 

  • i가 0인 경우 -1이 배열의 맨 끝 요소이므로 인덱스에 -1씩 추가하여 처리하고, j에는 -1을 추가한다.
>>> arr1[-3:9]
array([7, 8])

>>> arr1[:-3]
array([0, 1, 2, 3, 4, 5, 6])

>>> arr1[-3:2:-1]
array([7, 6, 5, 4, 3])

 

  • 인덱스 시작 종료보다 크면 길이가 0인 객체가 반환된다.
>>> arr1[5:2]
array([], dtype=int32)

 

  • [i:] 표기는 :를 중심으로 i가 인덱스의 시작이고 종료의 공백 표기는 배열의 요소 끝까지 인덱스 범위를 설정하여 처리하겠다는 의미이다.
>>> arr1[5:]
array([5, 6, 7, 8, 9])

>>> arr2[1:]
array([[3, 4, 5],
       [6, 7, 8]])
  • 2차원 배열 arr2의 인덱스처럼 축을 1개만 설정하면 인덱스 범위는 행에만 적용된다.

 

  • 배열 arr2 의 요소에서 특정 범위를 인덱싱하면 0축인 행과 1축인 열에 각각 슬라이싱을 실행할 수 있다.
>>> arr2
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
       
>>> arr2[:2, :2]
array([[0, 1],
       [3, 4]])
       
>>> arr2[:, ::-1]
array([[2, 1, 0],
       [5, 4, 3],
       [8, 7, 6]])

 

  • 2차원 배열을 슬라이싱할 때 0축이나 1축 중 하나에 정수를 입력하면 2차원이 1차원으로 낮아지고, 축 2개에 정수를 입력하면 스칼라가 된다.
>>> arr2[:, :]
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
       
>>> arr2[1, :]
array([3, 4, 5])

>>> arr2[1, 2]
5

 

  • 다음 예제의 arr3[0, :, 1]은 3차원 배열인 arr3을 0면, 모든 행, 1열을 선택한 배열로 인덱싱한다.
    • 이때 0과 1, 즉 정수가 2개 사용되었으므로 3차원 배열 객체 1차원 배열 객체가 된다는 점에 유의한다.
  • arr3[1, :, :]은 정수가 1개 적용되었으므로 2차원 배열 객체가 된다.
>>> arr3
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
        
>>> arr3[0, :, 1]
array([1, 5, 9])

>>> arr3[1, :, :]
array([[12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])

 

  • 다음 예제에서 3차원 배열 arr3을 인덱싱할 때 :2 0면과 1면, 1: 2행과 3행 그리고 :2 0열과 1열을 선택해 슬라이싱한다.
>>> arr3[:2, 1:, :2]
array([[[ 4,  5],
        [ 8,  9]],

       [[16, 17],
        [20, 21]]])

 

고급 인덱싱

  • 고급 인덱싱(Advanced Indexing) x[obj] 에서 선택 객체인 obj가 튜플 시퀀스 객체가 아니거나 데이터 타입 정수 또는 불리언의 ndarray일 때 사용할 수 있다.
  • 기본 인덱싱 를 반환하지만, 고급 인덱싱은 항상 데이터의 복사본을 반환한다.
  • 고급 인덱싱을 할 때 배열의 각 행에서 특정 요소를 선택해야 한다.
>>> arr = np.array([[1, 2], [3, 4], [5, 6]])
>>> arr
array([[1, 2],
       [3, 4],
       [5, 6]])
       
>>> arr[[0, 1, 2], [0, 1, 0]]
array([1, 4, 5])
  • 배열 arr 에서 행 인덱스 [0, 1, 2]로 전체 행을 선택하였다.
    • 그리고 행 인덱스는 열 인덱스 [0, 1, 0]에 일대일로 매핑된다.
      • 결국 0행 0열, 1행 1열, 2행 0열이 반환된다.

 

  • 기본 슬라이싱과 비슷한 기능을 실행하기 위해 브로드캐스팅(Broadcasting)을 사용할 수 있다.
    • 브로드캐스팅 : 더 작은 배열이 커다란 배열의 행과 열에 호환되도록 확대하는 것
  • 고급 인덱싱을 사용하면 다음처럼 4×3 배열 객체에서 행과 열을 각각 선택해 요소들을 처리할 수도 있다.
>>> arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
>>> rows = np.array([[0, 0], [3, 3]], dtype=np.intp)
>>> columns = np.array([[0, 2], [0, 2]], dtype=np.intp)
>>> arr[rows, columns]
array([[ 0,  2],
       [ 9, 11]])

 

 

  • 넘파이는 약간의 상수들을 포함한다.
  • numpy.newaxis
    • 함수가 아닌 상수
    • None의 별칭으로써 인덱싱할 때 유용하다.
    • 1차원 배열을 2차원으로, 2차원 배열을 3차원으로 차원을 1개씩 증가시킬 수 있다.
>>> np.newaxis is None
True

>>> arr = np.arange(25).reshape(5, 5)
>>> arr.shape
(5, 5)

>>> arr_3d = arr[np.newaxis]
>>> arr_3d.shape
(1, 5, 5)

 

  • 또한 상수 newaxis는 1차원 배열을 행 벡터 열 벡터로 변환할 수 있다.
>>> arr = np.arange(10)
>>> arr.shape
(10,)

>>> arr_row = arr[np.newaxis, :]
>>> arr_row.shape
(1, 10)

>>> arr_col = arr[:, np.newaxis]
>>> arr_col.shape
(10, 1)

 

  • 다음은 numpy.newaxis 를 사용하여 차원을 증가시켜 연산하는 예제이다.
>>> arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
>>> rows = np.array([0, 3], dtype=np.intp)
>>> columns = np.array([0, 2], dtype=np.intp)
>>> rows[:, np.newaxis]
array([[0],
       [3]], dtype=int64)
       
>>> arr[rows[:, np.newaxis], columns]
array([[ 0,  2],
       [ 9, 11]])

 

  • 다음은 인덱스에 사용하는 배열 스칼라 값으로 인덱싱한다.
  • 이때 스칼라 값의 인덱스가 모든 요소에 전파된다는 의미에서 브로드캐스팅이라 한다.
>>> arr = np.arange(15).reshape(3, 5)
>>> arr
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
       
>>> arr[np.array([0, 2]), 3]
array([ 3, 13])

 

  • 배열의 shape가 같지 않으면 브로드캐스팅을 할 수 없다.
  • 이때 newaxis를 사용해 차원을 증가시키면 배열 shape를 동일하게 만들 수 있다.
>>> arr1 = np.array([1, 2, 3, 4, 5])
>>> arr2 = np.array([11, 12, 13])
>>> arr1 + arr2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (5,) (3,)

>>> arr1_nx = arr1[:, np.newaxis]
>>> arr2_nx = arr2[:, np.newaxis]
>>> arr1_nx
array([[1],
       [2],
       [3],
       [4],
       [5]])
       
>>> arr2_nx
array([[11],
       [12],
       [13]])
       
>>> arr1_nx + arr2
array([[12, 13, 14],
       [13, 14, 15],
       [14, 15, 16],
       [15, 16, 17],
       [16, 17, 18]])
       
>>> arr2_nx + arr1
array([[12, 13, 14, 15, 16],
       [13, 14, 15, 16, 17],
       [14, 15, 16, 17, 18]])
  • arr1 arr2 shape가 같지 않아 arr1 + arr2 연산에서 오류가 발생했다.
    • 따라서 연산이 가능하도록 arr1_nx arr2_nx 차원을 하나 증대시켜 2개의 배열을 서로 더하면 열이 확대되는 브로드캐스팅을 할 수 있다.

 

불리언 배열로 인덱싱

  • 넘파이에서는 배열 객체의 고급 인덱싱을 위해 불리언 값을 인덱스로 사용할 수 있다.
    • 원하는 요소와 원하지 않는 요소를 명시적으로 선택하는 필터링을 할 수 있다.
      • 예) 배열의 차원과 같은 shape를 가지는 불리언 배열을 인덱스로 사용하면, 행으로 처리된 1차원 배열을 반환한다.
>>> arr = np.arange(12).reshape(3, 4)
>>> arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
       
>>> ind = arr>5
>>> ind
array([[False, False, False, False],
       [False, False,  True,  True],
       [ True,  True,  True,  True]])
       
>>> arr[ind]
array([ 6,  7,  8,  9, 10, 11])

 

  • 불리언 배열을 2차원 배열의 인덱스 배열로 사용하면 2차원 배열을 반환한다.
>>> ind[:, 1]
array([False, False,  True])

>>> arr[ind[:, 1]]
array([[ 8,  9, 10, 11]])

 

  • 2차원 불리언 배열 3차원 배열을 인덱싱하면 2차원 배열을 반환한다.
>>> arr = np.arange(24).reshape(2, 3, 4)
>>> arr
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
        
>>> ind = np.array([[True, False, True], [False, True, False]])
>>> arr[ind]
array([[ 0,  1,  2,  3],
       [ 8,  9, 10, 11],
       [16, 17, 18, 19]])
  • (2, 3)의 2차원 불리언 배열로, shape가 (2, 3, 4)인 3차원 배열을 인덱싱한 결과로써 shape가 (3, 4)인 2차원 배열이 된다.

 

슬라이싱과 인덱스 배열 처리

  • 인덱스는 슬라이싱과 함께 사용할 수 있다.
>>> arr = np.arange(12).reshape(3, 4)
>>> arr[np.array([1, 2]), 1:3]
array([[ 5,  6],
       [ 9, 10]])

 

  • 또한 브로드캐스팅된 불리언 인덱스와 함께 슬라이싱을 실행할 수 있다.
>>> ind = arr > 5
>>> ind
array([[False, False, False, False],
       [False, False,  True,  True],
       [ True,  True,  True,  True]])
       
>>> ind[:, 2]
array([False,  True,  True])

>>> arr[ind[:, 2], 1:3]
array([[ 5,  6],
       [ 9, 10]])

 

인덱스를 반환하는 numpy.nonzero(), numpy.transpose() 함수

  • numpy.nonzero() 함수
    • 0이 아닌 요소의 인덱스들을 반환하여 numpy.ndarray.nonzero 를 실행한 것과 같은 결과를 반환한다.
    • 각 배열의 차원에서 0이 아닌 요소의 인덱스를 포함하는 튜플을 반환한다.
>>> arr = np.array([[1, 0, 0], [0, 2, 0], [1, 1, 0]])
>>> arr
array([[1, 0, 0],
       [0, 2, 0],
       [1, 1, 0]])
       
>>> np.nonzero(arr)
(array([0, 1, 2, 2], dtype=int64), array([0, 1, 0, 1], dtype=int64))
  • 0이 아닌 요소의 인덱스 : [0, 0], [1, 1], [2, 0], [2, 1]
    • [0, 1, 2, 2] : 0이 아닌 값들의 첫 번째 인덱스 모음
    • [0, 1, 0, 1] : 0이 아닌 튜플의 두 번째 인덱스 모음

 

>>> arr[np.nonzero(arr)]
array([1, 2, 1, 1])

>>> np.transpose(np.nonzero(arr))
array([[0, 0],
       [1, 1],
       [2, 0],
       [2, 1]], dtype=int64)
  • 배열의 요소가 0이 아닌 값들을 정렬한다.
  • 축을 바꾸는 전치 함수 numpy.transpose() 를 사용하면 배열에서 0이 아닌 값을 나타내는 인덱스들을 그룹으로 처리할 수 있다.

 

>>> arr = np.arange(9).reshape(3, 3)
>>> arr > 3
array([[False, False, False],
       [False,  True,  True],
       [ True,  True,  True]])
       
>>> np.nonzero(arr > 3)
(array([1, 1, 2, 2, 2], dtype=int64), array([1, 2, 0, 1, 2], dtype=int64))
  • nonzero() 함수에 불리언 조건을 적용해 True인 인덱스를 반환하게 할 수 있다.

 

>>> (arr > 3).nonzero()
(array([1, 1, 2, 2, 2], dtype=int64), array([1, 2, 0, 1, 2], dtype=int64))
  • 불리언 배열에 nonzero() 메소드를 적용해도 같은 결과를 반환한다.

 

  • numpy.transpose() 함수
    • 배열의 축을 변환하여 뷰를 반환한다.
>>> arr = np.arange(4).reshape((2, 2))
>>> arr
array([[0, 1],
       [2, 3]])
       
>>> np.transpose(arr)
array([[0, 2],
       [1, 3]])
       
>>> arr1 = np.ones((1, 2, 3))
>>> np.transpose(arr1, (1, 0, 2)).shape
(2, 1, 3)
  • 2차원 배열인 arr을 전치하면 행이 열로, 열이 행으로 축이 변환된다.
  • 3차원 배열 arr1의 shape는 (1, 2, 3)이다.
  • 축은 0축, 1축, 2축 순서인데 이것을 1축, 0축, 2축 순서로 전치 처리하면 shape (2, 1, 3)을 반환한다.

 

  • 1차원 배열은 전치하면 원본 배열과 같은 뷰를 반환한다.
  • 전치 처리는 3가지 형태로 할 수 있다.
    • numpy.ndarray.T 속성을 이용하는 arr.T 형태
    • np.transpose(arr) 함수를 사용하는 방법
    • arr.transpose() 함수를 사용하는 방법 
>>> a = [1, 2, 3]
>>> a
[1, 2, 3]

>>> arr = np.array([a])
>>> b = np.array(a)
>>> b.T
array([1, 2, 3])

>>> arr.transpose()
array([[1],
       [2],
       [3]])

 

다차원 배열 전치

>>> arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
>>> arr
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])
       
>>> arr.transpose()
array([[1, 5],
       [2, 6],
       [3, 7],
       [4, 8]])

>>> arr1 = np.array([[[0, 1, 2, 3], [4, 5, 6, 7]], [[8, 9, 10, 11], [12, 13, 14, 15]]])
>>> arr1
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])
        
>>> arr1.T
array([[[ 0,  8],
        [ 4, 12]],

       [[ 1,  9],
        [ 5, 13]],

       [[ 2, 10],
        [ 6, 14]],

       [[ 3, 11],
        [ 7, 15]]])
  • 배열 arr은 0축인 행 2개, 1축인 열 4개를 가진 2차원 배열이다.
    • 전치하면 배열의 각 첫 번째 요소끼리 그룹화한 다음 두 번째 요소끼리 그룹화한다.
  • 3차원 배열 arr1은 0축인 면이 2개, 1축인 행이 2개, 2축인 열이 4개로 구성되어 있다.
    • 전치하면 shape가 (4, 2, 2)가 된다.

배열 arr1의 축

 

  • 다음으로 배열 arr1을 축이 (1, 0, 2)가 되도록 전치 처리해본다.
    • 0축과 1축을 바꾸고, 2축을 그대로 두는 전치
    • 이 경우, 면과 행은 변동되고 열이 변동되지 않으므로 전치 처리해도 형태는 같다.
>>> arr2 = np.transpose(arr1, (1, 0, 2))
>>> arr3 = arr1.transpose((1, 0, 2))
>>> arr2
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])
        
>>> arr3
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])
  • arr2 arr3의 결과는 같다.

 

  • 0축과 1축을 바꾸는 전치 처리 식을 알기 쉽게 표현하면 다음 그림과 같다.
    • 그림에서 2면의 첫 번째 행이 1면의 두 번째 행으로 이동한 것에 주목하자.

배열 arr1의 전치

 

  • arr1.T 속성을 사용하면 축 (0, 1, 2)가 (2, 1, 0)으로 전치된다.
    • 1축은 변화가 없고, 0축과 2축이 서로 교환되어 면이 4개 생긴다.
>>> arr4 = arr1.T
>>> arr4
array([[[ 0,  8],
        [ 4, 12]],

       [[ 1,  9],
        [ 5, 13]],

       [[ 2, 10],
        [ 6, 14]],

       [[ 3, 11],
        [ 7, 15]]])

 

예: 전치한 arr1, arr2, arr3, arr4 의 shape 확인하기
>>> arr1.shape
(2, 2, 4)

>>> arr2.shape
(2, 2, 4)

>>> arr3.shape
(2, 2, 4)

>>> arr4.shape
(4, 2, 2)

 

 

유니버셜 함수(Universal Function, ufunc)

  • 유니버셜 함수(Universal Function, ufunc)
    • 스칼라로 연산하는 수학적 함수들
    • 인터페이스를 제공하는 벡터화된 래퍼(Wrappers)
      • 래퍼(Wrapper) : 계산을 최소화하고 시스템을 호출할 수 있는 객체
      • 벡터화 : 데이터 타입이 정형화되었거나 실행 프로세스가 컴파일된 것
    • 실행 절차를 축약해 프로그램이 쉽게 처리되도록 하는 인터페이스들을 포함한다.
      • 예) 파이썬에서 반복문(Loop)으로 배열 데이터 요소에 다양한 연산을 실행할 때 처리 속도가 매우 느리므로 속도 개선을 위해 넘파이에서 새로운 인터페이스를 제공한다.

 

class numpy.ufunc

  • 유니버셜 함수는 함수를 실행하기 위해 numpy.func 클래스를 인스턴스한다.
  • ufunc 클래스는 유용한 속성 메소드를 가지고 있다.
  • 모든 ufunc 요소 단위로 배열을 연산하고 브로드캐스팅한다.
  • 유너버셜 함수를 사용하면 입력이 1개인 단항 연산과 입력이 2개인 이항 연산을 할 수 있다.
  • 유니버셜 함수는 속성을 가지고 있으나, 속성을 직접 설정할 수는 없다.

 

유니버셜 함수의 속성
속성 종류 기능
__doc__ ufunc의 docstring
__name__ ufunc의 name
ufunc.nin 입력 수
ufunc.nout 출력 수
ufunc.nargs 인수(Argument) 수
ufunc.ntypes 타입 수
ufunc.types 입력에서 출력으로 그룹화된 타입의 리스트를 반환
ufunc.identity identity 값
ufunc.signature 일반화된 ufunc가 연산하는 중심 요소 정의

 

  • 유니버셜 함수가 취급하는 입력 및 출력 인수 개수를 포함하는 데이터 속성 확인하기
>>> np.add.nin
2

>>> np.add.nout
1

>>> np.exp.nin
1

>>> np.exp.nout
1

 

  • 모든 ufunc reduce(), accumulate(), reduceat() outer() 메소드를 가진다.
    • 이들 메소드는 2개 인수를 입력하고 1개 출력을 반환하는 스칼라 ufunc에서 사용할 수 있다.
  • at() 메소드는 고급 인덱싱을 사용할 때 연산이 제 위치에서 실행되도록 한다.

 

유니버셜 함수의 메소드
메소드 종류 기능
reduce(a[, axist, dtype, out, keepdims]) 한 축을 따라 ufunc를 적용하여 a의 차원을 1개씩 축소한다.
accumulate(a[, axis, dtype, out]) 모든 요소에 연산자를 적용한 결과를 축적한다.
reduceat(a, indices[, axist, dtype, out]) 특정 슬라이싱 기능인 reduce를 단일 축에 실행한다.
outer(A, B, **kwargs) A에 a, B에 b인 모든 쌍(a, b)에 유니버셜 함수 연산인 ufunc op를 적용한다.
at(a, indices[, b]) 인덱스로 명시된 요소의 위치에서 a에 버퍼 없이(unbuffered) 바로 연산을 실행한다.

 

  • 유니버셜 함수는 단항 또는 이항 인수를 가지며, 호출할 수 있는 객체이다.
>>> np.add([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
array([ 2,  4,  6,  8, 10])

>>> arr = np.array([1, 2, 3, 4, 5])
>>> np.add.reduce(arr)
15
  • ufunc reduce() 메소드는 arr 시퀀스를 인수로 가지고 호출되고, 시퀀스의 요소에 대해 ufunc add()가 실행되어 차원이 1차원에서 0차원으로 감소된다.

 

  • 1차원 이상 배열 객체에 reduce() 메소드를 적용하면 기본 축인 0축에 감소를 실행한다.
>>> arr = np.array(([1, 2, 3], [4, 5, 6]))
>>> arr
array([[1, 2, 3],
       [4, 5, 6]])
       
>>> np.add.reduce(arr)
array([5, 7, 9])

>>> np.add.reduce(arr, axis=1)
array([ 6, 15])
  • 행 2개가 1개로 축소되면서 2차원이 1차원으로 감소한다.
  • axis=1 옵션을 설정하면 열 축에 감소를 적용하고, 열 3개가 2개로 줄어들면서 1차원으로 감소한다.

 

  • 유니버셜 함수 add() reduce() 메소드를 3차원 배열에 적용하면 2차원 배열이 되고, 2차원 배열에 적용하면 1차원 배열이 된다. 1차원 배열에 적용하면 요소의 값을 합산 스칼라 값이 된다.
>>> np.add.reduce(np.array([[[1, 2, 3, 4, 5]]]))
array([[1, 2, 3, 4, 5]])

>>> np.add.reduce(np.array([[1, 2, 3, 4, 5]]))
array([1, 2, 3, 4, 5])

>>> np.add.reduce(np.array([1, 2, 3, 4, 5]))
15

 

  • 유니버셜 함수 add() accumulate() 메소드는 모든 배열 요소에 연산자를 적용한 결과를 누계한다.
  • 유니버셜 함수 add()에 각각 accumulate() 메소드를 연산한 결과는 다음과 같다.
>>> np.add.accumulate([1, 2, 3, 4, 5])
array([ 1,  3,  6, 10, 15])

>>> np.multiply.accumulate([1, 2, 3, 4, 5])
array([  1,   2,   6,  24, 120])

 

  • 2차원 배열에 accumulate() 메소드 연산을 수행하면 기본 축인 0축이 감소된다.
  • axis=1로 옵션을 설정하면 열 축에 연산을 실행한다.
>>> arr = np.arange(12).reshape((3, 4))
>>> np.add.accumulate(arr)
array([[ 0,  1,  2,  3],
       [ 4,  6,  8, 10],
       [12, 15, 18, 21]])
       
>>> np.add.accumulate(arr, axis=1)
array([[ 0,  1,  3,  6],
       [ 4,  9, 15, 22],
       [ 8, 17, 27, 38]])

 

  • ufunc reduceat() 메소드는 단일 축 슬라이싱을 실행한다.
  • 두 번째 인수인 인덱스 len(arr)-1 이하인 수여야 한다.
>>> arr = np.arange(7)
>>> arr
array([0, 1, 2, 3, 4, 5, 6])

>>> np.add.reduceat(arr, [0, 3, 5, 6])
array([3, 7, 5, 6])
  • 배열 arr에서 arr[0:3], [3:5], [5:6], [6:]에 해당하는 요소를 각각 더한 값을 반환한다.

 

>>> np.linspace(0, 15, 16)
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12.,
       13., 14., 15.])
       
>>> arr = np.linspace(0, 15, 16).reshape(4, 4)
>>> arr
array([[ 0.,  1.,  2.,  3.],
       [ 4.,  5.,  6.,  7.],
       [ 8.,  9., 10., 11.],
       [12., 13., 14., 15.]])
       
>>> np.add.reduceat(arr, [0, 3, 1, 2, 0])
array([[12., 15., 18., 21.],
       [12., 13., 14., 15.],
       [ 4.,  5.,  6.,  7.],
       [ 8.,  9., 10., 11.],
       [24., 28., 32., 36.]])
  • 4개의 행으로 구성한 배열 arr np.add.reduceat을 실행해 1행+2행+3행, 4행, 2행, 3행, 1행+2행+3행+4행을 연산해 총 5개의 배열 행이 생성되도록 처리한다.
    • arr[0:3], [1:2], [2:0], arr[0:]의 범위를 인덱스를 설정한다.

 

  • ufunc outer() 메소드는 배열 A에서 a, 배열 B에서 b를 가지는 모든 쌍인 (a, b)에 ufunc op를 적용한다.
  • M=A.ndim, N=B.ndim이라고 할 때 op.outer(A, B)의 결과 C는 차원이 M+N인 배열이다.
>>> np.multiply.outer([1, 2, 3], [4, 5, 6])
array([[ 4,  5,  6],
       [ 8, 10, 12],
       [12, 15, 18]])

 

  • 다음과 같이 다차원 배열에 out() 메소드를 적용할 수 있다.
>>> arr1 = np.array([[1, 2, 3], [4, 5, 6]])
>>> arr1.shape
(2, 3)

>>> arr2 = np.array([[1, 2, 3, 4]])
>>> arr2.shape
(1, 4)

>>> arr = np.multiply.outer(arr1, arr2)
>>> arr.shape; arr
(2, 3, 1, 4)
array([[[[ 1,  2,  3,  4]],

        [[ 2,  4,  6,  8]],

        [[ 3,  6,  9, 12]]],


       [[[ 4,  8, 12, 16]],

        [[ 5, 10, 15, 20]],

        [[ 6, 12, 18, 24]]]])

 

유용한 유니버셜 함수

  • 넘파이에 정의된 60개 이상 유니버셜 함수들을 이용해 다양한 연산을 수행할 수 있다.
  • 예를 들어 add(a, b)를 사용하는 것과 같이, 배열에서 여러 ufunc를 자동으로 호출할 수 있다.
    • a와 b는 ndarray 객체이다.

 

수학 연산을 위한 유니버셜 함수 
함수 설명
add(x1, x2, /[, out, where, casting, order, ...]) Add arguments element-wise.
subtract(x1, x2, /[, out, where, casting, ...]) Subtract arguments, element-wise.
multiply(x1, x2, /[, out, where, casting, ...]) Multiply arguments element-wise.
matmul(x1, x2, /[, out, casting, order, ...]) Matrix product of two arrays.
divide(x1, x2, /[, out, where, casting, ...]) Returns a true division of the inputs, element-wise.
logaddexp(x1, x2, /[, out, where, casting, ...]) Logarithm of the sum of exponentiations of the inputs.
logaddexp2(x1, x2, /[, out, where, casting, ...]) Logarithm of the sum of exponentiations of the inputs in base-2.
true_divide(x1, x2, /[, out, where, ...]) Returns a true division of the inputs, element-wise.
floor_divide(x1, x2, /[, out, where, ...]) Return the largest integer smaller or equal to the division of the inputs.
negative(x, /[, out, where, casting, order, ...]) Numerical negative, element-wise.
positive(x, /[, out, where, casting, order, ...]) Numerical positive, element-wise.
power(x1, x2, /[, out, where, casting, ...]) First array elements raised to powers from second array, element-wise.
float_power(x1, x2, /[, out, where, ...]) First array elements raised to powers from second array, element-wise.
remainder(x1, x2, /[, out, where, casting, ...]) Returns the element-wise remainder of division.
mod(x1, x2, /[, out, where, casting, order, ...]) Returns the element-wise remainder of division.
fmod(x1, x2, /[, out, where, casting, ...]) Returns the element-wise remainder of division.
divmod(x1, x2[, out1, out2], / [[, out, ...]) Return element-wise quotient and remainder simultaneously.
absolute(x, /[, out, where, casting, order, ...]) Calculate the absolute value element-wise.
fabs(x, /[, out, where, casting, order, ...]) Compute the absolute values element-wise.
rint(x, /[, out, where, casting, order, ...]) Round elements of the array to the nearest integer.
sign(x, /[, out, where, casting, order, ...]) Returns an element-wise indication of the sign of a number.
heaviside(x1, x2, /[, out, where, casting, ...]) Compute the Heaviside step function.
conj(x, /[, out, where, casting, order, ...]) Return the complex conjugate, element-wise.
conjugate(x, /[, out, where, casting, ...]) Return the complex conjugate, element-wise.
exp(x, /[, out, where, casting, order, ...]) Calculate the exponential of all elements in the input array.
exp2(x, /[, out, where, casting, order, ...]) Calculate 2**p for all p in the input array.
log(x, /[, out, where, casting, order, ...]) Natural logarithm, element-wise.
log2(x, /[, out, where, casting, order, ...]) Base-2 logarithm of x.
log10(x, /[, out, where, casting, order, ...]) Return the base 10 logarithm of the input array, element-wise.
expm1(x, /[, out, where, casting, order, ...]) Calculate exp(x) - 1 for all elements in the array.
log1p(x, /[, out, where, casting, order, ...]) Return the natural logarithm of one plus the input array, element-wise.
sqrt(x, /[, out, where, casting, order, ...]) Return the non-negative square-root of an array, element-wise.
square(x, /[, out, where, casting, order, ...]) Return the element-wise square of the input.
cbrt(x, /[, out, where, casting, order, ...]) Return the cube-root of an array, element-wise.
reciprocal(x, /[, out, where, casting, ...]) Return the reciprocal of the argument, element-wise.
gcd(x1, x2, /[, out, where, casting, order, ...]) Returns the greatest common divisor of |x1| and |x2|
lcm(x1, x2, /[, out, where, casting, order, ...]) Returns the lowest common multiple of |x1| and |x2|

 

  • numpy.subtract() 함수 사용 예
>>> np.subtract(1.0, 4.0)
-3.0

>>> arr1 = np.arange(9).reshape((3, 3))
>>> arr2 = np.arange(3.0)
>>> np.subtract(arr1, arr2)
array([[0., 0., 0.],
       [3., 3., 3.],
       [6., 6., 6.]])

 

  • numpy.power() 함수 사용 예
>>> arr1 = range(6)
>>> arr1
range(0, 6)

>>> np.power(arr1, 3)
array([  0,   1,   8,  27,  64, 125], dtype=int32)

>>> arr2 = [1.0, 2.0, 3.0, 3.0, 2.0, 1.0]
>>> np.power(arr1, arr2)
array([ 0.,  1.,  8., 27., 16.,  5.])

 

  • 유니버셜 함수에 브로드캐스팅을 적용할 수 있다.
>>> arr3 = np.array([[1, 2, 3, 3, 2, 1], [1, 2, 3, 3, 2, 1]])
>>> arr3
array([[1, 2, 3, 3, 2, 1],
       [1, 2, 3, 3, 2, 1]])
       
>>> np.power(arr1, arr3)
array([[ 0,  1,  8, 27, 16,  5],
       [ 0,  1,  8, 27, 16,  5]])

 

삼각 함수 연산을 위한 유니버셜 함수
함수 설명
sin(x, /[, out, where, casting, order, ...]) Trigonometric sine, element-wise.
cos(x, /[, out, where, casting, order, ...]) Cosine element-wise.
tan(x, /[, out, where, casting, order, ...]) Compute tangent element-wise.
arcsin(x, /[, out, where, casting, order, ...]) Inverse sine, element-wise.
arccos(x, /[, out, where, casting, order, ...]) Trigonometric inverse cosine, element-wise.
arctan(x, /[, out, where, casting, order, ...]) Trigonometric inverse tangent, element-wise.
arctan2(x1, x2, /[, out, where, casting, ...]) Element-wise arc tangent of x1/x2 choosing the quadrant correctly.
hypot(x1, x2, /[, out, where, casting, ...]) Given the "legs" of a right triangle, return its hypotenuse.
sinh(x, /[, out, where, casting, order, ...]) Hyperbolic sine, element-wise.
cosh(x, /[, out, where, casting, order, ...]) Hyperbolic cosine, element-wise.
tanh(x, /[, out, where, casting, order, ...]) Compute hyperbolic tangent element-wise.
arcsinh(x, /[, out, where, casting, order, ...]) Inverse hyperbolic sine element-wise.
arccosh(x, /[, out, where, casting, order, ...]) Inverse hyperbolic cosine, element-wise.
arctanh(x, /[, out, where, casting, order, ...]) Inverse hyperbolic tangent element-wise.
degrees(x, /[, out, where, casting, order, ...]) Convert angles from radians to degrees.
radians(x, /[, out, where, casting, order, ...]) Convert angles from degrees to radians.
deg2rad(x, /[, out, where, casting, order, ...]) Convert angles from degrees to radians.
rad2deg(x, /[, out, where, casting, order, ...]) Convert angles from radians to degrees.

 

  • numpy.sin() 함수 사용 예
>>> np.sin(np.pi/2)
1.0

>>> np.sin(np.deg2rad(90))
1.0

>>> np.sin(np.array((0., 30., 45., 60., 90.)) * np.pi/180.)
array([0.        , 0.5       , 0.70710678, 0.8660254 , 1.        ])

 

  • matplotlib.pyplot 모듈을 사용해 sin() 함수 그래프 그리기
import matplotlib.pyplot as plt

arr = np.linspace(-np.pi, np.pi, 201)
plt.plot(arr, np.sin(arr))
plt.xlabel('Angle [rad]')
plt.ylabel('sin(x)')
plt.axis('tight')
plt.show()

 

비트 단위 연산을 위한 유니버셜 함수
함수 설명
bitwise_and(x1, x2, /[, out, where, ...]) Compute the bit-wise AND of two arrays element-wise.
bitwise_or(x1, x2, /[, out, where, casting, ...]) Compute the bit-wise OR of two arrays element-wise.
bitwise_xor(x1, x2, /[, out, where, ...]) Compute the bit-wise XOR of two arrays element-wise.
invert(x, /[, out, where, casting, order, ...]) Compute bit-wise inversion, or bit-wise NOT, element-wise.
left_shift(x1, x2, /[, out, where, casting, ...]) Shift the bits of an integer to the left.
right_shift(x1, x2, /[, out, where, ...]) Shift the bits of an integer to the right.

 

  • 사용 예
>>> np.bitwise_and(13, 17)
1

>>> np.binary_repr(12)
'1100'

>>> np.bitwise_and([14, 3], 13)
array([12,  1], dtype=int32)

 

비교(Comparison) 연산을 위한 유니버셜 함수
함수 설명
greater(x1, x2, /[, out, where, casting, ...]) Return the truth value of (x1 > x2) element-wise.
greater_equal(x1, x2, /[, out, where, ...]) Return the truth value of (x1 >= x2) element-wise.
less(x1, x2, /[, out, where, casting, ...]) Return the truth value of (x1 < x2) element-wise.
less_equal(x1, x2, /[, out, where, casting, ...]) Return the truth value of (x1 <= x2) element-wise.
not_equal(x1, x2, /[, out, where, casting, ...]) Return (x1 != x2) element-wise.
equal(x1, x2, /[, out, where, casting, ...]) Return (x1 == x2) element-wise.
logical_and(x1, x2, /[, out, where, ...]) Compute the truth value of x1 AND x2 element-wise.
logical_or(x1, x2, /[, out, where, casting, ...]) Compute the truth value of x1 OR x2 element-wise.
logical_xor(x1, x2, /[, out, where, ...]) Compute the truth value of x1 XOR x2, element-wise.
logical_not(x, /[, out, where, casting, ...]) Compute the truth value of NOT x element-wise.
maximum(x1, x2, /[, out, where, casting, ...]) Element-wise maximum of array elements.
minimum(x1, x2, /[, out, where, casting, ...]) Element-wise minimum of array elements.
fmax(x1, x2, /[, out, where, casting, ...]) Element-wise maximum of array elements.
fmin(x1, x2, /[, out, where, casting, ...]) Element-wise minimum of array elements.

 

플로팅(Floating) 연산을 위한 유니버셜 함수
함수 설명
isfinite(x, /[, out, where, casting, order, ...]) Test element-wise for finiteness (not infinity and not Not a Number).
isinf(x, /[, out, where, casting, order, ...]) Test element-wise for positive or negative infinity.
isnan(x, /[, out, where, casting, order, ...]) Test element-wise for NaN and return result as a boolean array.
isnat(x, /[, out, where, casting, order, ...]) Test element-wise for NaT (not a time) and return result as a boolean array.
fabs(x, /[, out, where, casting, order, ...]) Compute the absolute values element-wise.
signbit(x, /[, out, where, casting, order, ...]) Returns element-wise True where signbit is set (less than zero).
copysign(x1, x2, /[, out, where, casting, ...]) Change the sign of x1 to that of x2, element-wise.
nextafter(x1, x2, /[, out, where, casting, ...]) Return the next floating-point value after x1 towards x2, element-wise.
spacing(x, /[, out, where, casting, order, ...]) Return the distance between x and the nearest adjacent number.
modf(x[, out1, out2], / [[, out, where, ...]) Return the fractional and integral parts of an array, element-wise.
ldexp(x1, x2, /[, out, where, casting, ...]) Returns x1 * 2**x2, element-wise.
frexp(x[, out1, out2], / [[, out, where, ...]) Decompose the elements of x into mantissa and twos exponent.
fmod(x1, x2, /[, out, where, casting, ...]) Returns the element-wise remainder of division.
floor(x, /[, out, where, casting, order, ...]) Return the floor of the input, element-wise.
ceil(x, /[, out, where, casting, order, ...]) Return the ceiling of the input, element-wise.
trunc(x, /[, out, where, casting, order, ...]) Return the truncated value of the input, element-wise.

 

 

728x90
그리드형(광고전용)

'In-depth Study > NumPy' 카테고리의 다른 글

[NumPy] 넘파이 적용  (0) 2022.04.14
[NumPy] 배열 객체 관리와 연산  (0) 2022.04.13
[NumPy] 넘파이 배열  (0) 2022.04.13
[NumPy] 넘파이(NumPy) 개요  (0) 2022.04.13
⚠️AdBlock이 감지되었습니다. 원할한 페이지 표시를 위해 AdBlock을 꺼주세요.⚠️


📖 Contents 📖