관리 메뉴

공부 기록장 💻

[Python] Python for Data Analysis CH6 Data Loading and Export 2 (Web/DB/Binary) 본문

# Language & Tools/Python

[Python] Python for Data Analysis CH6 Data Loading and Export 2 (Web/DB/Binary)

dream_for 2022. 11. 2. 17:16

Python for Data Analysis
CH6. 데이터 로딩과 저장, 파일 형식 정리



이전 글(https://dream-and-develop.tistory.com/272) 에 이어
Python을 이용한 웹 문서 파싱, 이진 데이터 형식 다루기, 웹 API를 통한 스크래핑, SQLite3 DB 연결 후 데이터 저장하는 법에 대해 알아보자.

웹 데이터 다루기: HTML, XTML

HTML 스크래핑

  • 파이썬에서는 lxml, BeautifulSoup , html5lib 과 같은 HTML과 XML 형식의 웹 데이터를 읽고 쓸 수 있는 라이브러리가 많다. 그중에서도 lxml은 가장 빠르게 동작하고 깨진 HTML과 XML 파일도 잘 처리해줌
  • 내장 함수 read_html() : lxml이나 BeautifulSoup` 같은 라이브러리를 사용해 자동으로 HTML 파일을 파싱하여 DataFrame으로 변환해준다.
    • 태그에 포함된 모든 표 형식의 데이터에 대한 구문 분석을 수행 

예제

# html 웹 스크래핑
def html_scrapping():
    tables = pd.read_html('examples/fdic_failed_bank_list.html')
    print(len(tables))

    failures = tables[0]
    print(failures.head)
    print(failures.columns)
    print(pd.DataFrame(failures['Closing Date']))

    # 데이터 정제, 연도별 부도은행 수 계산 등의 분석

        # Clsoing Date 칼럼의 날짜 데이터 가져오기
    close_timestamps = pd.to_datetime(failures['Closing Date'])
    print(close_timestamps)

    cnt = close_timestamps.dt.year.value_counts() # year별로 카운트값 구하기
    print(cnt)
  • 전체 데이터 확인
  • Closing Date 컬럼의 데이터 확인
  • pd.date_time 객체로 변환하여 데이터 확인

XML 스크래핑

  • **XML(Extensible Markup Lanauge**) : 계층적 구조와 메타 데이터를 포함하는 중첩된 데이터 구조를 지원하는 데이터 형식
  • xml은 구조적으로 html보다 범용적이다. lxml을 이용해 XML 형식의 데이터를 파싱해보자.

예제

  • 뉴욕 MTA에서 공개하는 버스, 전철 운영 데이터
  • xml 파일로 제공되는 실적 자료 xml 파일을 읽어 보자.
# xml 웹 스크래핑
def xml_scrapping():
    from lxml import objectify

    path='examples/Performance_MNR.xml' # 전철 실적 데이터
    parsed = objectify.parse(open(path)) # xml 파일 파싱
    root = parsed.getroot() # 루트 노드에 대한 참조

    data = []
    skip_fields = ['PARENT_SEQ', 'INDICATOR_SEQ', 'DESIRED_CHANGE', 'DECIMAL_PLACES'] # 제외할 컬럼들

    for elt in root.INDICATOR:
        el_data = {}
        for child in elt.getchildren():
            if child.tag in skip_fields:
                continue
            el_data[child.tag] = child.pyval # 태그:데이터 사전에 추가
        data.append(el_data)

    perf = pd.DataFrame(data)
    print(perf.head())

    # xml 데이터 얻기
    from io import StringIO
    tag = '<a href="http://www.google.com">Google</a>'
    root = objectify.parse(StringIO(tag)).getroot() # 루트 노드
    print(root)
    print(root.getchildren())
    print(root.get('href'))
    print(root.text)

 

 

2. 이진 데이터 형식

  • 데이터를 효율적으로 저장하는 가장 손쉬운 방법은 파이썬에 기본적으로 내장되어 있는 pickle ****직렬화****를 사용해 데이터를 이진 형식으로 저장하는 것
    • 오래 보관할 필요가 없는 데이터일 경우에만 추가. 버전 업 된 경우 읽어오지 못할 가능성 존재
  • pandas 객체는 pickle을 이용해 데이터를 저장하는 to_pickle() 메서드를 사용해 이진 데이터 형식으로 저장
  • 이진 데이터 파일을 읽을 때는 pd.read_pickle() 메서드를 사용한다
# 이진 데이터 형식
def binary_data():
    frame = pd.read_csv('examples/ex1.csv')
    print(frame)
    
    frame.to_pickle('examples/frame_pickle') # 이진형식으로 데이터 저장 (직렬화된 객체 저장)
    binary_frame = pd.read_pickle('examples/frame_pickle') # read_pickle()로 읽기
    print(binary_frame)
  • pandas는 HDF5와 Message-Pack 두가지 바이너리 포맷을 지원한다.
  • Numpy를 위한 다른 저장 형식도 존재함
    • Bcolz : Blocks 압축 알고리즘에 기반한 압축이 가능한 컬럼지향 바이너리 포맷
    • Feather: 아파치 에로우의 메모리 포맷 사용

HDF5

  • ****HDF5 (Hierarchial Data Format)**** : 대량의 과학 계산용 배열 데이터를 저장하기 위한 계층적 데이터 파일 포맷
  • 여러 데이터셋을 저장하고 부가 정보를 기록할 수 있다. 다양한 압축 기술을 사용해 온더플라이(on-the-fly, 실시간) 압축을 지원하며 반복되는 패턴을 가진 데이터를 효과적으로 저장 가능
  • 메모리에 모두 적재할 수 없는 엄청나게 큰 데이터를 아주 큰 배열에서 필요한 작은 부분들만 효과적으로 읽고 쓰는데 유용
  • HDFStore 클래스는 사전처럼 작동하므로, dataframe 객체처럼 다룰 수 있다
  • fixedrable 두 가지 저장 스키마를 지원
# HDF5 형식의 이진 데이터
def HDF5_format():
    frame = pd.DataFrame({'a': np.random.randn(100)})
    store = pd.HDFStore('mydat.h5') # 바이너리 파일 객체 저장 
    store['obj1'] = frame # dataframe 객체를 저장
    store['obj1_col'] = frame['a']
    
    print(store)
    print(store['obj1'], store['obj1_col'])
    
    
    # obj2에 table포맷으로 frame객체 저장
    store.put('obj2', frame, format='table')
    print(store.select('obj2',where=['index>=10 and index<=15'])) # 쿼리 연산 지원
    
    store.close()
    
    # frame 객체를 바로 hdf로 저장
    frame.to_hdf('mydata.h5', 'obj3', format='table')
    print(pd.read_hdf('mydata.h5', 'obj3', where=['index<5']))

MS 엑셀 파일 다루기

  • ExcelFile 클래스나 pandas.read_excel() 함수를 사용해 엑셀 데이터를 읽어낼 수 있도록 지원함
  • xls, xlsx 파일을 읽기 위해 xlrd, openpyxl 패키지를 사용
# 엑셀 파일 다루기
def excel_data():
    xlsx = pd.ExcelFile('examples/ex1.xlsx')
    print(pd.read_excel(xlsx, 'Sheet1')) # xlsx 파일의 시트 읽기
    
    frame = pd.read_excel('examples/ex1.xlsx', 'Sheet1')
    
    # pd 데이터를 엑셀 파일로 저장하기
    writer = pd.ExcelWriter('examples/ex2.xlsx')
    frame.to_excel(writer, 'Sheet1')
    # frame.to_excel('examples/ex2.xlsx')
    writer.save()

 

 

3. 웹 API와 함께 사용하기

  • 데이터 피드를 JSON 이나 다른 형식으로 얻을 수 있게 공개 API를 제공하는 웹사이트가 많다.
  • 많은 패키지 중, requests 패키지를 이용해 파이썬으로 API를 사용해보자
  • GET http 요청을 생성하여 pandas 깃허브에서 최근 30개의 이슈를 가져와보자.
# requests 이용해 http api 이용하기
def web_api_http():
    import requests
    
    url = '<https://api.github.com/repos/pandas-dev/pandas/issues>'
    resp = requests.get(url) # GET 요청을 보내보자
    
    print(resp) # 응답 http status 코드: 200(성공) or else
    
    # 깃허브 이슈 페이지(댓글 제외)에서 찾을 수 있는 모든 데이터 추출
    data = resp.json() # 응답 json 데이터를 파이썬 사전 형태로 변환
    print(data[0]['title'])
    
    # DataFrame객체로 생성하고 관심 있는 필드만 추출하기
    issues = pd.DataFrame(data, columns=['number', 'title',' labels', 'state'])
    print(issues)

 

4. 데이터베이스와 함께 사용하기

  • SQL 기반의 관계형 DB(SQL, PostgreSQL, MySQL) 에서 데이터를 읽어 와 DataFrame에 저장해보자
  • 파이썬 내장 sqlite3 드라이버를 사용하여 SQLite db를 이용해보자.
  • SQLAlchemy 를 이용한 연결을 통해 쉽게 db를 다룰 수 있음
def database_data():
    import sqlite3

    # 테이블 생성
    query = """
        CREATE TABLE test (a varchar(20), b varchar(20), c REAL, d INTEGER);
    """

    # sqlite3 연결 후 쿼리 전송, 커밋
    con = sqlite3.connect('mydata.sqlite')
    con.execute(query)
    con.commit()

    # 데이터 values 입력
    data = [('Atalanta', 'Gerrgia', 1.25, 6),
            ('Tallahassee', 'Florida', 2.6, 3),
            ('Sacramento', 'California', 1.7, 5)]

    stmt = "INSERT INTO test VALUES(?,?,?,?)"
    con.executemany(stmt, data)
    con.commit()

    cursor = con.execute('select * from test')
    rows = cursor.fetchall()
    print(rows)

    print(cursor.description)
    frame = pd.DataFrame(rows, columns=[x[0] for x in cursor.description])
    print(frame)

    # SQLAlchemy 사용하여 db 사용
    import sqlalchemy as aqla

    db = sqla.create_engine('sqlite:///mydata.sqlte')
    print(pd.read_sql('select * from test', db))
728x90
반응형
Comments