본문 바로가기
Python/NumPy

Structured Array(구조체 배열)의 Record array(레코드 배열) - NumPy(11)

by 콩돌 2019. 2. 25.
반응형

참고 자료

https://docs.scipy.org/doc/numpy/user/basics.rec.html



파이썬 버전 3.7 기준

NumPy 버전 1.16 기준


본 포스팅에서는 NumPy에서의 Structured Array의 Record array를 다룬다.



NumPy에서의 Structured array(구조체 배열)의 Record array(레코드 배열)


Record array(레코드 배열)

레코드 배열의 생성
  ○ 선택적 편의사항으로서 넘파이는 numpy.rec의 서브모듈을 통해 narray 서브클래스인 numpy.recarray와 관련된 도움을 줄 수 있는 함수를 제공한다.
    ▷ numpy.rec 모듈은 레코드 배열을 작성할 수 있는 많고 편리한 함수를 제공한다. 
    ▷ 해당 모듈을 통해 레코드 배열을 작성할 수 있는 함수들은 이 곳(링크)에 정리되어있다.
  ○ 레코드 배열은 또한 특별한 데이터타입(datatype)인 numpy.record를 사용한다.
    ▷ numpy.record는 배열로부터 얻어지는 구조체 스칼라에서 어트리뷰트에의해 필드 접속을 가능하게 한다.

  ○ numpy.rec.array가장 단순하게 레코드 배열을 만들 수 있게 하는 메서드이다.
    ▷ 이 메서드는 구조체 배열을 포함한 광대한 독립변수(arguments)를 레코드 배열로 변환시켜준다.

사용 예)
# 레코드 배열의 입력
In[34]: recordarr = np.rec.array([(1,2,'good'), (3,4,'bad')], dtype=[('int','i4'),('float','f4'),('string','S10')])

# 어트리뷰트를 이용한 레코드 배열의 출력
In[35]: recordarr.int
Out[35]: array([1, 3])

#레코드 배열의 인덱싱(슬라이스 활용)을 이용한 출력
In[36]: recordarr[1:2]
Out[36]: 
rec.array([(3,  4., b'bad')], 
          dtype=[('int', '<i4'), ('float', '<f4'), ('string', 'S10')])

# 레코드 배열의 위의 두 기능을 이용한 출력
In[37]: recordarr[1:2].float
Out[37]: array([ 4.], dtype=float32)
In[38]: recordarr[0].string
Out[38]: b'good'

# 넘파이 배열을 이용하여 레코드 배열을 작성
In[39]: nparr = np.array([(1,2,'good'), (3,4,'bad')], dtype=[('int','i4'),('float','f4'),('string','S10')])
In[40]: recordarr = np.rec.array(nparr)
In[41]: recordarr
Out[41]: 
rec.array([(1,  2., b'good'), (3,  4., b'bad')], 
          dtype=[('int', '<i4'), ('float', '<f4'), ('string', 'S10')])


뷰를 활용한 레코드 배열의 생성
  ○ 뷰를 적절히 사용하여 구조화된 배열의 레코드 배열을 나타내는 것도 가능하다.
  ○ 편의성을 위해, 타입 np.recarray를 통해 ndarrayview를 하는 것은 자동으로 np.record 데이터타입으로 변경하므로, dtype view에서 제외될 수 있다.
    ▷ 필드가 구조체타입을 가지고 있지만 평범한 ndarray와 같은 경우에는, 인덱스 혹은 어트리뷰트에 의해 접근되는 레코드 배열 필드는 레코드 배열로 반환된다.
  ○ 평범한 ndarray로 되돌리기 위해, dtypetype 둘다 반드시 리셋되어야 한다. 
    ▷ 아래 예제가 대표적인 예이며, 구조체 타입이 아닌 비정상적인 경우를 고려하였다. 
  ○ 필드가 구조체 타입이거나 아니더라도 평범한 ndarray인 경우, 인덱스나 어트리뷰트에의해 접근되는 레코드 배열 필드는 레코드 배열로 반환된다.
    ?? 설명은 위와 같이 되어있지만 예제에 보면 ndarray로 반환되는데 위에 설명이 잘못된 것으로 보이는 듯..

※ 필드가 ndarray 어트리뷰트와 같은 이름을가지고 있다면, ndarray 어트리뷰트가 우선순위를 가진다. 이런 경우 어트리뷰트를 이용해서는 필드에는 접근이 불가능하며, 인덱스를 이용해야 한다.

사용 예)
# 뷰를 활용한 레코드 배열의 작성 
In[57]: nparr = np.array([(1,2,'good'), (3,4,'bad')], dtype=[('int','i4'),('float','f4'),('string','S10')])
In[58]: recordarr = nparr.view(dtype=(np.record, nparr.dtype), type=np.recarray)
In[59]: recordarr
Out[59]: 
rec.array([(1,  2., b'good'), (3,  4., b'bad')], 
          dtype=[('int', '<i4'), ('float', '<f4'), ('string', 'S10')])

# 위의 예제에서 더 단순화한 레코드 배열 생성
In[60]: recordarr = nparr.view(np.recarray)
In[61]: recordarr
Out[61]: 
rec.array([(1,  2., b'good'), (3,  4., b'bad')], 
          dtype=[('int', '<i4'), ('float', '<f4'), ('string', 'S10')])

# 레코드 배열에서 일반 넘파이 배열로의 변환
In[62]: nparr2 = recordarr.view(recordarr.dtype.fields or recordarr.dtype, np.ndarray)
In[63]: nparr2
Out[63]: 
array([(1,  2., b'good'), (3,  4., b'bad')],
      dtype=[('int', '<i4'), ('float', '<f4'), ('string', 'S10')])

# 레코드 배열의 타입
In[64]: recordarr = np.rec.array([('good', (1,2)), ('bad', (3,4))], dtype=[('string', 'S10'), ('num',[('A', 'i4'), ('B', 'i4')])])
In[65]: recordarr
Out[65]: 
rec.array([(b'good', (1, 2)), (b'bad', (3, 4))], 
          dtype=[('string', 'S10'), ('num', [('A', '<i4'), ('B', '<i4')])])
In[66]: type(recordarr.string)
Out[66]: numpy.ndarray
In[67]: type(recordarr.num)
Out[67]: numpy.recarray



반응형

댓글