Intro

 

 

받으려고 하는 데이터셋 파일이 .mat(매트랩) 형식으로 되어 있어서, 이를 scipy.io.loadmat을 이용해서 받았다.

(아래에 stackoverflow 출처를 올리겠지만, 질문을 올리신 분과 정확히 똑같은 상황에 처해있었다.)

 

 

받은 파일은 dictionary 형식이였고... bounding box 좌표가 들어있는 key를 찾아서 출력해보았더니

 

사이즈가 (70, ) 였다. 그래서 이걸 보고 아 ~ 70장 사진에 대한 bbox 좌표인가 보다 하고 [0]을 출력해보았다.

 

처음 봤을때는 뭔가 숫자가 엄청 많아서 이게 뭐지? 하고 .shape로 찍어봤는데 출력 값이 () 이였다. 

 

분명 데이터 값이 저렇게 많은데 shape를 찍었을 때 ()으로 나오는 것을 보니 심상치 않았다.

 

그래서 이게 뭐지???? 하고 type()으로 출력해보았더니 결과값이 <class 'numpy.void'> 이였다.

 

numpy.ndarray나 많이 봤지, void는 처음이라....... 많이 당황했다.

 

처음에는 이름만 보고 데이터가 비어있다는 의미인가? 했는데 비어있다면 실제로 데이터 값이 없어야 하니 그건 또 말이 안 되는 것 같았다.

 

따라서 numpy.void가 무엇이고, 이를 어떻게 활용할 수 있는지에 대해서 알아볼 필요성이 생겨 검색을 하다보니 적합한 글을 찾아 이를 정리해보려고 한다.

 

 

 

What is numpy.void?

 

numpy documentation에 따르면(http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html), numpy.void type은 flexible data type으로 정의된다. 기본적으로, numpy.void type은 변수와 관련해서 이미 정의된 type이 없는 데이터 타입이다. 이미 정의된 type이란, float, uint8, bool, string 등등의 data type을 말하는 것이다.

 

 

void는 더 포괄적이고 융통성 있는 type을 수용하며, void는 이미 정의된 데이터 타입 중 하나로 반드시 결정되지 않는 데이터 타입을 위해 존재한다. 이러한 상황은 대개 struct에서 loading 할 때 마주하게 되는데, 각 element가 다양한 field와 관련 있는 다양한 데이터 타입을 가지고 있는 경우이다. 각 structure element는 다른 데이터 타입의 조합을 가질 수 있으며, 이러한 structure element를 가진 instance를 나타내기 위해 numpy.void를 사용한다.

 

 

documentation에 따르면, 우리가 다른 데이터 타입들에 적용하던 operation을 동일하게 적용할 수 있다. 

 

 

예시를 통해 조금 더 정확하게 알아보도록 하자.

 

import numpy as np
dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])

dt는 데이터 타입을 나타내는데, tuple로 구성되고 각 tuple은 (fieldname, datatype, shape)로 구성된다. 

 

 

field가 대체 뭘 얘기하는지 명확하게 써있지 않아서 이것저것 찾아봤는데도 못 찾아서... 대략 유추하기로는 데이터 타입의 element를 나타내는 용어인 듯하다.

 

 

데이터 타입이 두 개의 tuple로 구성되었다는 것은, 결국에 데이터가 2개로 구성되어야 한다는 의미이다.

 

 

즉, 첫 번째 데이터의 fieldname은 'name'이고, 16-bit인 string이 된다.

 

 

두 번째 데이터의 fieldname은 'grades'이고, (1, 2) 형태를 가지는 float 값이 될 것이다.

 

 

 

 

위 데이터 타입을 이용해서, 실제 데이터를 만들어보자.

 

x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)

 

x라는 데이터를 만들었고, 이는 두 개의 elements를 가지고 있다. 

 

각 element는 아까 위에서 정의해준 데이터 타입대로 만들어진 것을 확인할 수 있다.

 

 

 

여기서 주의해야 할 점은, 데이터 x 자체의 타입은 numpy.ndarray를 만족한다는 점이다.

 

 

그 대신, 데이터 x의 elements는 numpy.void를 만족한다. 왜냐하면, 각 element는 'name'과 'grades'라고 하는 다른 데이터 타입 두 개를 모두 포함하기 때문이다.

 

 

따라서,

x[1]

로 입력하게 되면,

 

 

 

('John', [6.0, 7.0])

이라는 두 번째 element를 얻을 수 있으며,

 

type(x[1])

 

이에 대해서 type을 출력하게 만들면,

 

x[1] type:  <class 'numpy.void'>

라고 출력이 된다. 

 

 

 

즉, 내가 처음에 마주했던 numpy.void는 이 데이터 안에 다양한 형태의 데이터 타입이 존재하는 데이터였던 것이다....!

 

 

 

자 그럼 여기서 실제로 numpy.void를 마주했다고 했을 때, 각 데이터 타입의 이름을 알아야만 출력이 가능하다.

 

물론, index를 이용해서 출력할 수도 있긴 하다.

 

예를 들면,

 

print("x[1][0]: ", x[1][0])
print("x[1][1]: ", x[1][1])

으로 출력시키면,

 

 

 

x[1][0]:  John
x[1][1]:  [6. 7.]

이라는 출력 값을 얻게 된다.

 

 

 

index를 이용하지 않고, 데이터 타입의 이름을 이용해서 출력하려면 어떻게 해야 할까?

 

 

 

print(x[1].dtype)

 

해당 numpy.void 데이터에 대해서 .dtype을 하게 되면,

 

 

[('name', '<U16'), ('grades', '<f8', (2,))]

 

이렇게 각 데이터 타입(fieldname, datatype, shape)에 대한 정보를 알 수 있다.

 

 

 

따라서 이 fieldname을 이용해서 출력해보자면,

 

 

print('x[1]["name"]: ', x[1]['name'])
print('x[1]["grades"]: ', x[1]['grades'])

 

이렇게 해서 시키면, 출력이

 

 

 

x[1]["name"]:  John
x[1]["grades"]:  [6. 7.]

 

이런 식으로 출력이 된다. 

 

 

 

 

결론(Conclusion)

 

 

 

1. 'numpy.void'는 다양한 데이터 타입을 포함하고 있는 데이터를 나타내는 데이터 타입이다. 따라서, 데이터 안에 정수형, 실수형, 문자열 등 다양한 형태의 데이터 타입이 존재한다.

 

 

2. numpy.void로 되어 있는 데이터를 핸들링할 때, index를 이용해서 데이터를 뽑을 수도 있지만 만약 정확하게 fieldname을 지정해서 뽑아내고 싶다면 .dtype을 이용해서 각 데이터 타입의 fieldname을 알아낸 뒤 이를 이용해 주자!

 

 

 

 

참고자료

stackoverflow.com/questions/25247190/numpy-void-type-how-to-use-it

 

numpy.void type - how to use it?

I loaded a MATLAB .mat file via scipy.io.loadmat and it gave me a list of numpy.void objects. Can someone tell me what are they, how they can be used and where can I get some reference documentati...

stackoverflow.com

docs.scipy.org/doc/numpy-1.15.1/user/basics.rec.html

 

 

 

+ Recent posts