(파이썬) 6장 데이터 로딩, 저장 , 파일 형식

*일반적으로 입출력은 몇가지 작은 범주로 나눌 수 있으며 텍스트 파일을 이용하는 방법, 데이터베이스를 이용하는 방법, 웹 API를 이용해서 네트워크를 불러오는 방법이있다.

1. 텍스트 파일 이용하는 방법

*pandas 파일 파싱 함수

read_csv : 파일,URL 또는 파일과 유사한 객체로부터 구분된 데이터를 읽어온다. 데이터 구분자는 쉼표(,)를 기본으로 한다.
read_table:  파일, URL , 또는 파일과 유사한 객체로r부터 구분된 데이터를 읽어온다. 데이터 구분자는 탭('\t')을 기본으로 한다.

read_fwf : 고정폭 칼럼 형식에서 데이터를 읽어온다.(구분자가 없는 데이터)
read_clippboard: 클립보드에 있는 데이터를 읽어오는 read_table함수, 웹페이지에서 표를 긁어올 때 유용하다.


-->위 함수는 DataFrame으로 읽어오는 함수로, 몇가지 종류의 옵션을 받는다.

  • 색인: 반환하는 DataFrame에서 하나 이상의 칼럼을 색인으로 지정할 수 있다. 파일이나 사용자로부터 칼럼의 이름을 받거나 아무것도 받지 않을 수 있다.
  • 자료형 추론과 데이터 변환: 사용자가 정의 값 변환과 비어 있는 값을 위한 사용자 리스트를 포함한다.
  • 날짜분석: 여러 칼럼에 걸쳐 있는 날짜와 시간 정보를 하나의 칼럼에 조합해서 결과에 반영한다.
  • 반복: 여러 파일에 걸쳐 있는 자료를 반복적으로 읽어 올 수 있다.

   예)
     !cat ch06/ex1.csv

    a,b,c,d,message
    1,2,3,4,hello
    5,6,7,8,world
    9,10,11,12,foo

**이 파일은 쉼표로 구분되어 있기 때문에 read_csv를 사용해 DataFrame으로 읽어 올 수 있다.

예) df=pd.read_csv('ch06/ex1.csv')

출력:
    a   b   c   d  message
0  1   2   3   4    hello
1  5   6   7   8    world
2  9   10  11 12   foo

**read_table에 구분자를 쉼표로 지정해서 읽어올 수 있다.

예) pd.read_table('ch06/ex1.csv',sep=',')


**모든 파일에 칼럼의 이름이 있는건 아니다.

예) 1,2,3,4,hello
    5,6,7,8,world
    9,10,11,12,foo

이 파일을 직접 읽어오려면 몇가지 옵션이 있는데 ,pandas가 자동으로 칼럼이름을 생성하도록 하거나 직접 칼럼이름을 지정할 수도 있다.

예) pd.read_csv('ch06/ex2.csv',header=None)

또는 

pd.read_csv('ch06/ex2.csv',names=['a','b','c','d','message'])


    a  b  c  d   message
0  1  2  3  4     hello
1  5  6  7  8      world
2  9  10 11 12    foo


** message 칼럼을 색인으로 하는 DataFrame을 반환하려면 index_col 인자에 네 번째 또는 'message'라는 이름을 가진 칼럼을 지정해서 색인으로 만들 수 있다.

예) names=['a','b','c','d','message']

 pd.read_csv('ch06/ex2.csv', names=names, index_col='message')

             a    b   c   d
message  
hello       1    2    3    4
world      5    6    7    8
foo         9    10  11   12


** 가끔 고정된 구분자 없이 공백이나 다른 패턴으로 필드르 구분해 놓는 경우가 있는데, 이럴떄는 read_table의 구분자로 정규표현식을 사용한다.
다음과 같은 파일이 있다고 가정하자

예) list(open('ch06/ex3.txt'))
            
[           A      B      C\n
 aaa       0      1      2\n
 bbb      3     4       5\n
 ccc       6     7       8\n
 ddd      9     10     11\n]

-->직접 파일을 고쳐도 되지만 이 파일은 여러 개의 공백문자로 필드가 구분되어 있으므로 이를 표현할 수 있는 정규표현식 \s+를 사용해서 처리할 수 있다.

예) result=pd.read_table('ch06/ex3.txt',sep='\s+')

-->이 경우 첫 번쨰 로우는 다른 로우보다 칼럼이 하나 적기 때문에 read_table은 첫번째 칼럼이 DataFrame의 색인이 되어야 한다고 추론한다.

파서 함순느 파일 형식에서 발생할 수 있는 매우 다양한 예외를 처리할 수 있도록 추가 인자를 가지고 있는데, 예를들면 skiprows를 이용해서 첫번째, 두번째, 네번째 로우를 건너 뛸 수 있다.

예) pd.read_csv('ch06/ex4.csv',skiprows=[0,2,3])


**누락된 값을 잘 처리하는 일은 파일을 읽는 과정에서 자주 발생하는 일이다. 보통 텍스트 파일에서 누락된 값은 표기되지 않거나 (비어있는 문자열) 구분하기 쉬운 특수한 문자로 표기 된다. 기본적으로 pandas는 NA, -1, #IND, NULL 처럼 비어있는 값으로 흔히 통용되는 문자를 인식해서 비어있는 값으로 처리한다.


** na_values 옵션은 리스트나 문자열 집합을 받아서 누락된 값을 처리한다.

예) result=pd.read_csv('ch06/ex5.csv', na_values=['NULL'])

    출력:
              something     a    b    c    d   message
   0           one            1    2    3    4     hello
   1           two            5    6   NaN  8     world
   2           three          9    10   11   12     foo




<<read_csv/ read_table 함수 인자>>

1. path :  파일시스템에서의 위치, URL, 파일 객체를 나타내는 문자열
2. sep or delimiter  :   필드를 구분하기 위해 사용할 연속된 문자나 정규표현식
3. header   :   칼럼이 이름으로 사용할 로우의 번호  기본 값은 0(첫 로우) 이며 헤더가 없으면 None으로 지정할 수 있다.

4. index_col  : 색인으로 사용할 칼럼번호나 이름, 계층적 색인을 지정할 경우 리스트를 넘길 수 있다.

5. names : 칼럼의 이름으로 사용할 리스트,header=None과 함께 사용한다.
6. skiprows : 파일의 시작부터 못할 로우의 개수 또는 무시할 로우번호가 담긴 리스트
7. na_values : NA값으로 처리할 값들의 나열
8. comment : 주석으로 분류되어 파싱하지 않을 문자 혹은 문자열
9. parse_dates : 날짜를 datetime으로 변환할지의 여부, 기본값은 False이며 True일 경우 모든 칼럼에 다 적용된다. 리스트를 넘기면 변환할 칼럼을 지정할 수 있는데, [1,2,3]을 넘기면 각각의 칼럼을 datetime으로 변환하고, [[1,3]]을 넘기면 1,3 번 칼럼을 조합해서 하나의 datetime으로 변환한다.


10. keep_date_col : 여러 칼럼을 datetime으로 변환했을 경우 원래 칼럼을 남겨둘지의 여부, 기본 값은 False
11. converters : 변환시 칼럼에 적용할 함수를 지정한다. 예를들어, {'foo': f}는 'foo'칼럼에 f함수를 적용한다. 전달하는 사전의 키 값은 칼럼이름이나 번호가 될 수 있다.

12. dayfirst : 모호한 날짜 형식일 경우 국제형식으로 간주한다.(7/6/2012는 2012년 6월 7일로 간주한다). 기본값은 False

13. date_parser :  날짜 변환시 사용할 ㅎㅁ수

14. nrows :  파일의 첫 일부만 읽어올 때 처음 몇줄을 읽을 것인지 지정한다.
15. iterator : 파일을 조금씩 읽을 때 사용하도록 TextParser객체를 반환하도록 한다. 기본값은 False

16. chunksize :  TextParser 객체에서 사용할, 한번에 읽을 파일의 크기
17. skip_footer : 무시할 파일의 마지막 줄 수
18. verbose :  파싱 결과에 대한 정보를 출력한다. 숫자가 아닌 값이 들어있는 칼럼이면서 누락된 값이 있다면 줄 번호를 출력한다. 기본값은 False
19. encoding : 유닠드 인코딩 종류를 지정한다.UTF-8로 인코딩된 텍스트일 경우 'utf-8'로 지정한다.

20. squeeze : 로우가 하나뿐이라면 Series객체를 반환한다. 기본값은 False
21. thousands : 숫자를 천 단위로 끊을 때 ',' 나'.' 같은 구분자





<2. 텍스트 파일 조금씨 읽어오기>

*파일을 전체를 읽는 대신 처음 몇줄만 읽어보고 싶다면 nrows옵션을 주면된다.

예)
pd.read_csv('ch06/ex6.csv', nrows=5)

*파일을 여러 조각에 나누어서 읽고 싶다면 chunksize옵션으로 로우의 개수를 주면된다.

chunker=pd.read_csv('ch06/ex6.csv', chunksize=1000)

*read_csv 에서 반환된 TextParser 객체를 이용해서 chunksize에 따라 분리된 파일을 순회 할 수 있다. 예를들어, ex6.csv 파일을 순회하면서 'key' 칼럼에 있는 값을 세어보려면 다음처럼 하면된다.

예)chunker=pd.read_csv('ch06/ex6.csv', chunksize=1000)

tot=Series([])
for piece in chunker:
   tot=tot.add(piece['key'].value_counts(), fill_value=0)

tot=tot.order(ascending=False)

tot[:10]

출력:

E  368
X  364
L  346
O  343
Q  340
M  338
J  337
F  335
K  334
H  330




<3. 데이터를 텍스트 형식으로 기록하기>

**읽어오기와 마찬가지로 데이터를 구분자로 구분된 형시긍로 내보내는 것도 가능하다.


예) data.to_csv('ch06/out.csv')

*구분자를 사용하는 것도 가능하다.

예)
 data.to_csv(sys.stdout, sep='|')

** 결과에서 누락된 값은 비어있는 문자열로 나타내는데, 이것 역시 웒는 값으로 지정할 수 있다.

예) data.to_csv(sys.stdout, na_rep='NULL')

결과:

 ,somthing,a,b,c,d,message
0,one,1,2,3.0,4,NULL
1,two,5,6,NULL,8,world
2,three,9,10,11.0,12,foo


**다른 옵션이 명시되지 않으면 로우와 칼럼의 이름도 함께 기록된다. 로우와 칼럼의 이름을 포함하지 않으면 다음과 같이 사용한다.

예)
data.to_csv(sys.stdout, index=False, header=False)

**칼럼의 일부분만 기록할 수도 있고, 순서를 직접 지정할 수도 있다.

예)
data.to_csv(sys.stdout, index=False, cols=['a','b','c'])


**Series에도 to_csv메소드가 있다.

예) 
dates=pd.date_range('1/1/2000', periods=7)
ts=Series(np.arange(7), index=dates)
ts.to_csv('ch06/tseries.csv')

결과:

2000-01-01    00:00:00,0
.
.
.
2000-01-07    00:00:00.,6

**약간 복잡하게 헤더를 없애고 첫 번째 칼럼을 색인으로 하면 read_csv메소드로 Series객체를 얻을 수 있지만 from_csv메소드가 좀더 편리하고 간단하게 문제를 해결해준다.

예)
Series.from_csv('ch06/tseries.csv', parse_date=True)

2000-01-01   0
...
...
..
2000-01-07    6



<4. 수동으로 구분 형식 처리하기>

**간혹 read_table에서 읽을 수 없는 잘못된 형식의 줄이 포함된 데이터는 드물지 않게 발견할 수 있다.

다음 CSV파일을 보자.

"a","b","c"
"1","2","3"
"1","2","3","4"

**구분자가 한글자인 파일은 파이썬 내장 csv모듈을 이용해서 처리할 수 있는데, 열려진 파일 객체를 csv.reader함수에 넘기기만 하면된다.

예)

import csv
f=open('ch06/ex7.csv')

reader=csv.reader(f)

--->파일을 읽듯이 reader를 순회하면 둘러싸고 있던 큰따옴표(")가 제거된 튜플을 얻을 수 있다.



**CSV파일은 다양한 형태로 존재할 수 있는데 다양한 구분자, 문자열을 둘러싸는 방법, 개행문자 같은 것은 csv.Dialect를 상속받아 새로운 클래스를 정의해서 해결할 수 있다.

예)
class my_dialect(csv.Dialect):
    lineterminator='\n'
    delimiter=';'
    quotechar=' " '

reader=csv.reader(f,dialect-my_dialect)

**서브클래스를 정의하지 않고, csv.reader에 키워드 인자로 각 CSV파일의 특징을 지정해서 전달해도 된다.

reader=csv.reader(f, delimiter='|')



<CSV관련 옵션>

1. delimiter :  필드를 구분하기 위한 한글자 짜리 구분자. 기본값은 ','
2. lineterminator : 파일을 저장할 때 사용할 개행문자. 기본값은 '\r\n'. 파일을 읽을 때는 이 값을 무시하며 자동으로 플랫폼별 개행문자를 인식한다.
3. quotechar : 각 필드에서 값을 둘러싸고 있는 문자.기본값은 ' " '

4. quoting : 값을 읽거나 쓸 때 둘러쌀 문자 컨벤션. csv.QUOTE_ALL(모든 필드에 적용), csv.QUOTE_MINIMAL(구분자 같은 특별한 문자가 포함된 필드만 적용), csv.QUOTE_NONE(값을 둘러싸지 않음)

5. skipinitialspace : 구분자 뒤에 있는 공백문자를 무시할지의 여부, 기본값은 False
6. doublequote : 값을 둘러싼느 문자가 필드 내에 존재할 경우의 처리 여부. True면 그 문자까지 모두 둘러싼다.

7. escapechar : quoting이 csv.QUOTE_NONE일때, 값에 구분자와 같은 문자가 있을 경우 구별할 수 있또록 해주는 이스케이프 문자('\'같은) ,기본값은 None




*****좀더 복잡하거나 구분자가 한글자를 초과하는 고정 길이를 가진다면 csv모듈을 사용할 수 없다. 이런 경우에는 줄을 나누고 문자열의 split메소드나 정규표현식 메소드인 re.split등을 이용해서 가공하는 작업을 해야 한다.

**CSV같은 구분자로 구분된 파일을 기록하려면 csv.writer를 이용하면 된다. csv.writer는 이미 열린,쓰기가 가능한 파일 객체를 받아서 csv.reader 와 동일한 옵션으로 파일을 기록한다

예)
with open ('mydata.csv', 'w') as f:
  writer=csv.writer(f,dialect=my_dialect)
  writer.writerow(('one','two','three'))
  writer.writerow(('1','2','3'))
  writer.writerow(('4','5','6'))
  writer.writerow(('7','8','9'))

댓글

이 블로그의 인기 게시물

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬

(18장) WebSocekt과 STOMP를 사용하여 메시징하기