본문 바로가기
Python/NumPy

genfromtxt을 통한 배열(array) 생성 상세 - NumPy(5)

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

참고 자료

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



파이썬 버전 3.7 기준

NumPy 버전 1.15 기준


본 포스팅에서 다루는 범위는 다음과 같다.

genfromtxt에서의 delimiter, autostrip, comments, skip_header, skip_footer, usecols, names, defaultfmt, converters, missing_values, filling_values, usemask 등.



파일으로부터의 배열(array)의 생성(2)


앞 포스팅에서는 genfromtxt의 기초적인 구조를 구성했다면 본 포스팅에서는 genfromtxt의 기능들에 대해 상세하게 설명해보고자 한다.

genfromtxt() 함수를 사용하기 위한 사전 import)

import numpy as np

from io import StringIO

※ io모듈은 반드시 import할 필요는 없다.

  - 본 포스팅에선 txt파일을 직접 하진 않고 문자열(string)으로 정의된 변수를 사용하는데 이런 경우 genfromtxt함수에서는 이 변수를 주소나 작업영역에 있는 파일로 인식하여 함수가 제대로 작동하지 않으므로, io 모듈에서 StringIO 함수를 사용한다.



요소 나누기 및 가공

delimiter

  ○ 한글로는 구획문자란 의미를 가지고 있다.

  ○ 즉, 파일에서 배열의 요소를 나누어 입력하기 위한 구분문자를 입력받는다.

  ○ 기본값은 None인데 탭과 스페이스 같이 빈 공간에서 나눈다는 의미이다.

  ○ 이 입력 변수는 문자열을 입력받을 경우와 숫자를 입력받을 경우 구분하는 방법이 달라진다.

    ▷ 문자열을 입력 받을 경우 해당 문자열에서 구분하여 나눈다.

    ▷ 숫자를 사용할 경우 숫자에 해당하는 커서의 단위로 나눈다.


사용 예)

# 문자를 사용하는 경우

In[3]: d = u"1,2,3,4 \n 4, 5, 6, 7"

In[4]: np.genfromtxt(StringIO(d), delimiter=",")

Out[4]: 

array([[1., 2., 3., 4.],

       [4., 5., 6., 7.]])


# 단일 숫자를 사용하는 경우

In[5]: d= u"123456789\n222333444"

In[6]: np.genfromtxt(StringIO(d), delimiter=3)

Out[6]: 

array([[123., 456., 789.],

       [222., 333., 444.]])


# 튜플 숫자를 사용하는 경우

In[7]: d= u"123456789\n222333444"

In[8]: np.genfromtxt(StringIO(d), delimiter=(1,3,5))

Out[8]: 

array([[1.0000e+00, 2.3400e+02, 5.6789e+04],

       [2.0000e+00, 2.2300e+02, 3.3444e+04]])


autostrip

  ○ 자동으로 뜯어낸다는 의미이다.

  ○ 즉, 스페이스와 같은 공간을 자동으로 없에버리는 기능을 가지고 있다. 

  ○ 기본값은 거짓(False)으로 해당 값은 꺼져있다. 

  ○ NumPy에 문자열 등의 자료형을 넣을 경우에 유용하다.


사용 예)

# 데이터 입력
In[3]: d = u"1  , ggg  ,  aaa,   5\n   1, x,g   , 165 "


#  autostrip 기능 사용 전

In[4]: np.genfromtxt(StringIO(d), delimiter=",", dtype="|U5", autostrip=False)

Out[4]: 

array([['1  ', ' ggg ', '  aaa', '   5'],

       ['1', ' x', 'g   ', ' 165']], dtype='<U5')


autostrip 기능 사용 후

In[5]: np.genfromtxt(StringIO(d), delimiter=",", dtype="|U5", autostrip=True)

Out[5]: 

array([['1', 'ggg', 'aaa', '5'],

       ['1', 'x', 'g', '165']], dtype='<U5')


comments

  ○ 텍스트 파일에 주석이 포함되어있는 경우, comments 독립변수를 통해 주석을 제거할 수 있다.

  ○ 기본 값은 None이며 해당 값은 사실상 꺼져있다고 볼 수 있다.

  ○ 해당 기능을 사용하기 위해서는 주석에 해당하는 문자(열)을 입력하면 된다.


사용 예)

In[9]: d = u'''# comment

    ...:        1,2,3,4

    ...:        5,6,7,8

    ...:        9,10,11,12 #comment

    ...:        '''

In[10]: np.genfromtxt(StringIO(d), delimiter=",", dtype="|U5", comments="#")

Out[10]: 

array([['1', '2', '3', '4'],

       ['5', '6', '7', '8'],

       ['9', '10', '11', '12']], dtype='<U5')



데이터 스킵과 열의 선택

skip_header & skip_footer

  ○ 파일 전후단에 필요없는 데이터가 있을 경우 skip_header나 skip_footer를 이용하여 필터링이 가능하다.

  ○ 해당 변수들은 정수만을 입력으로 받는다. 

    ▷ 정수로 해당되는 라인까지 제거시켜 데이터를 입력받는다.


사용 예)

In[14]: d = u"""1,2,3,4,5

     ...:        6,7,8,9,10

     ...:        11,12,13,14,15

     ...:        16,17,18,19,20

     ...:        21,22,23,24,25

     ...:        26,27,28,29,30"""

In[15]: np.genfromtxt(StringIO(d), delimiter=",", skip_header=1, skip_footer=2)

Out[15]: 

array([[ 6.,  7.,  8.,  9., 10.],

       [11., 12., 13., 14., 15.],

       [16., 17., 18., 19., 20.]])


usecols

  ○ use columns, 즉 사용하고자 하는 열을 선택하는 기능이다. 

  ○ 이 변수는 정수 혹은 정수 시퀀스를 입력으로 받는다.

    ▷ 입력받는 정수는 배열로 만들고자 하는 인덱스이다.

    ▷ 파이썬 인덱싱 내부 기능중에 음수를 사용할 수 있는 것과 같이 여기서도 음수 입력이 가능하며, 의미역시 동일하다.

    ▷ names 변수를 이용하는 경우에 한에서는 문자(열)도 입력이 가능하다.


사용 예)

In[21]: d = u"""1,2,3,4,5

     ...:        6,7,8,9,10

     ...:        11,12,13,14,15

     ...:        16,17,18,19,20

     ...:        21,22,23,24,25

     ...:        26,27,28,29,30"""

In[22]: np.genfromtxt(StringIO(d), delimiter=",", usecols=(3,4))

Out[22]: 

array([[ 4.,  5.],

       [ 9., 10.],

       [14., 15.],

       [19., 20.],

       [24., 25.],

       [29., 30.]])



이름의 설정

names

  ○ 열의 인덱스에 이름을 부여할 수 있다.

  ○ 해당 변수를 활용하면, NumPy의 배열을 파이썬 내장 자료형중 하나인 딕셔너리와 유사하게 만들어 줄 수 있다.

    ▷ 또한, 표와 유사하게 만들어 줄 수 있다.

  ○ 열의 이름을 입력하는 방법은 여러가지가 존재한다.
    ① names에 직접 입력 하는것이 아니라  dtype에 입력하는 방법
    ② 콤마로 나뉘어진 문자열 사용: names= "A, B, C"
    ③ 시퀀스형 자료형 사용: names= ['A', 'B', 'C']
    ④ 논리형(boolean) 사용: names= True
      - 논리형을 사용하는 경우 가장 입력데이터의 가장 윗줄을 names로 입력한다.
      - skip_header 변수와 같이 사용되는 것이 권장 된다.


사용 예)

# 데이터 입력

In[3]: d = u"1 2 3 4 \n 5 6 7 8"


# ①번 방법

In[4]: np.genfromtxt(StringIO(d), dtype=[('a', int), ('b', int), ('c', int), ('d', int)])

Out[4]: 

array([(1, 2, 3, 4), (5, 6, 7, 8)],

      dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<i4'), ('d', '<i4')])


②번 방법

In[5]: np.genfromtxt(StringIO(d), names="a, b, c, d")

Out[5]: 

array([(1., 2., 3., 4.), (5., 6., 7., 8.)],

      dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8'), ('d', '<f8')])


③번 방법

In[6]: np.genfromtxt(StringIO(d), names=['a','b','c','d'])

Out[6]: 

array([(1., 2., 3., 4.), (5., 6., 7., 8.)],

      dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8'), ('d', '<f8')])


④번 방법

In[7]: np.genfromtxt(StringIO(d), names=True)

Out[7]: 

array((5., 6., 7., 8.),

      dtype=[('1', '<f8'), ('2', '<f8'), ('3', '<f8'), ('4', '<f8')])


defaultfmt

  ○ 열 이름을 입력하고자 하고, 열 이름을 정해진 형식에 맞춰 입력하고자 할 때 사용할 수 있는 기능이다.

  ○ 문자열 형태로 입력을 받는다.

    ▷ defaultfmt= 'format_%i'

      - 바로 위의 예제에서 format_은 모든 이름에 포함되는 문자열이다.

      - %i는 열의 번호가 들어가는 자리이다.

  ○ 기본값은 defaultfmt='f%i' 이다.

  ○ %i 대신 %02i로 입력할 경우 2자리 수로 입력된다.


사용 예)

# 데이터 입력

In[11]: d = u"1 2 3 4 \n 5 6 7 8"


# %i만 사용
In[12]: np.genfromtxt(StringIO(d), defaultfmt="Format_%i", dtype=(int, int, int, float))
Out[12]: 
array([(1, 2, 3, 4.), (5, 6, 7, 8.)],
      dtype=[('Format_0', '<i4'), ('Format_1', '<i4'), ('Format_2', '<i4'), ('Format_3', '<f8')])

%02i로 사용
In[13]: np.genfromtxt(StringIO(d), defaultfmt="V_%02i", dtype=(int, int, int, float))
Out[13]: 
array([(1, 2, 3, 4.), (5, 6, 7, 8.)],
      dtype=[('V_00', '<i4'), ('V_01', '<i4'), ('V_02', '<i4'), ('V_03', '<f8')])



데이터 컨버전

converters

  ○ 특별한 양식의 데이터 형식(예: 날짜[yyyy/mm/dd], 퍼센트[xx%] 등)에서 데이터를 추출할 때 사용할 수 있는 기능이다.

  ○ converter 변수를 통해 데이터를 가공하여 NumPy 배열을 제작할 수 있다.

    ▷ 데이터 가공을 위한 함수는 사용자가 직접 작성해야한다.

    ▷ converters는 딕셔너리를 입력으로 받는다. 

      - key는 열의 이름 혹은 열 인덱스를 입력으로 받는다.

      - value는 함수를 입력으로 받는다.

    ▷ 즉, 사용자가 데이터 가공을 위한 함수를 작성한 후 이를 converters에 입력하면된다.


사용 예)

In[23]: d = u"100,200,300\n400,500,600"

In[24]: func =lambda x: float(x)/100

In[25]: np.genfromtxt(StringIO(d), delimiter=',', converters={0: func})

Out[25]: 

array([[  1., 200., 300.],

       [  4., 500., 600.]])



데이터의 누락과 채우기

converters 독립변수를 통해 데이터처리를 유용하게 할 수 있으나, 단순한 데이터처리를 하는데에도 코드 작성자가 그 만큼 함수작성에 시간을 더 투자해야하므로 비효율적일 수 있다. 데이터의 누락과 누락된 데이터를 채우는 것에 대해서는 아래와 같은 변수들에 값을 입력하여 처리하면 간단히 이러한 작업을 수행할 수 있다.


missing_values

  ○ 기본적으로 빈 문자열은 누락된 것으로 여겨진다. 

  ○ 누락되거나 유효하지 않은 데이터를 표현하기 위해 특수한 문자열(예: N/A, ??? 등)과같은 복잡한 문자열을 고려할 수 있다.

  ○ missing_values 변수는 다음 3가지 방식으로 입력을 받을 수 있다.

    ▷ 하나의 문자열 혹은 콤마로 분리된 문자열

      - 이 경우는 모든 열에 대해서 누락된 데이터에 관한 마커로서 문자열이 사용된다.

    ▷ 문자열의 시퀀스

      - 이 경우 각각의 요소는 순서대로 열에 연결된다.

    ▷ 딕셔너리

      - 딕셔너리의 값이 문자열이거나 혹은 문자열의 시퀀스이다. 

      - key값은 열의 인덱스(정수형태) 혹은 열의 이름이 가능하다. 

      - 추가적으로 None 값을 가지는 키는 모든 열에 대해 사용가능한 기본값을 정의하는데 사용된다. 


filling_values

  ○ 누락된 데이터를 찾는 방법은 존재 하고 있으나, 데이터가 누락됬다는 것을 표시할 수 있게하는 것이 filling_values이다.

  ○ 누락된 데이터 위치에 채우는 기본값은 자료형에 따라 다르며 다음과 같다.

    ▷ bool: False

    ▷ int: -1

    ▷ float: np.nan

    ▷ complex: np.nan+0j

    ▷ string: '???'

  ○ filling_values 역시 missing_values와 동일한 방법으로 입력을 받을 수 있다.

    ▷ 하나의 문자열 혹은 콤마로 분리된 문자열

    ▷ 문자열의 시퀀스

    ▷ 딕셔너리


사용 예)

In[35]: d = 'Non, 2, 3\n5, ???, 7'

In[36]: np.genfromtxt(StringIO(d), delimiter=',', missing_values={0:"Non", 1:"???", 2:" "}, filling_values={0:-999, 1:0, 2:-1}, dtype=int)

Out[36]: 

array([[-999,    2,    3],

       [   5,    0,    7]])


usemask

  ○ usemask 변수를 True로 설정하면 불린마스크(boolean mask)를 구성함으로써 누락된 데이터의 발생을 추적할 수 있다.

    ▷ 데이터가 누락됬으면 True를 아니면 False를 출력한다.

  ○ usemask를 True로 설정할 경우 MaskedArray가 출력으로 나온다.



반응형

댓글