KT AIVLE School 3기/Pandas

KT Aivle DX트랙 18일차

Do잇 2023. 2. 24. 22:31

오늘의 교육과정은 데이터 수집이다.

 

이전까지는 로컬에서 기존파일을 읽거나 Github에서 데이터를 읽어와서 데이터를 다루고 다듬고 분석했던 수업들이었다.

예를 들어 로컬에서 읽어온다면, 

# 라이브러리 불러오기
import pandas as pd

# 데이터 읽어오기
temp = pd.read_csv('로컬파일명.csv')

# 확인
temp.head()

Github에서 읽어온다면,

# 라이브러리 불러오기
import pandas as pd

# 데이터 읽어오기
path = 'https://raw.githubusercontent.com/Gitjub주소.csv'
temp = pd.read_csv(path)

# 확인
temp.head()

 ~   이런 식이었다.

 

하지만, 로컬에서 읽는 건 필요한 데이터를 꼭 다운로드해야 하고, 시간이 지나면 과거 데이터가 되면서 최신 데이터를 다시 다운로드받아야 하는 번거로움이 있으며, 데이터를 남들과 공유할 수 없다는 단점이 있다. 

Github는 자료가 변경되면 불러온 쥬피터에서 새로 실행했을 때 변경된 자료가 반영된다는 점이 장점이지만, 누군가는 Github관리 기술을 가지고 꾸준히 관리해야 한다는 단점이 있고 처음 자료공유를 위해서 업로드해야 하는 번거로움이 있다. 이 또한 로컬과 마찬가지로 시간이 지나면 서서히 과거 데이터가 된다. 

 

우리가 필요한 데이터를 다운로드 하지 않으면서 남들과 같은 최신데이터를 실시간으로 볼 수는 없을까?

 

오늘 배운 오픈 API가 그 해답이다.

> 오픈 API란? 

                                (↔ 프라이빗 Private API)

Open API 네이버 지식백과 검색결과

 

공개 API라고도 불리는 오픈(Open) API 는 개발자라면 누구나 사용할 수 있도록 공개된 API를 말하며, 개발자에게 사유 응용 소프트웨어나 웹 서비스의 프로그래밍적인 권한을 제공한다. 

 

네이버 지식백과에서도 설명하듯이 네이버지도, 구글맵, 오픈스트리트맵 등이 대표적인 예라고 하며, 메타블로그도 그 예시라고 한다. 최근에 코로나 질병으로 인해 네이버클라우드플랫폼의 API지원을 받아 라이브코로나, 코로나 맵 등의 서비스가 생겼다고도 설명하셨다.

 

> 국내 주요 오픈 API사이트

를 강조해서 알려주셨다.  추후 우리에게 도움이 많이 될 사이트들이라며 강조하셨다.                                    

아래 아이콘을 누르면 해당 사이트로 바로 이동한다.

 

● 공고데이터포털(추천)

행정안정부에서 운영

● 서울 열린데이터 광장(추천)

 

서울시에서 운영

● 문화데이터 광장

문화체육관광부 운영

● 공간정보 오픈플랫폼

국토교통부에서 운영

 

> response ( JSON & XML )

 

- JSON(JavaScript Object Notation) → 딕셔너리형태 { } → 데이터프레임 → 분석

  데이터를 전송, 저장할 때 많이 쓰는 경량의 DATA 교환방식.

 

- XML(extensible markup language) → <key> value 형태

  인터넷 웹페이지를  만드는 HTML을 획기적으로 개선하여 만든 언어이다.

  

키, 벨류형태는 동일하기 때문에 두 언어가 호환이 가능하다는 것을 강조하셨다.

 

>>  오픈 API 사용 방법

우선 가장 힘들었던 회원가입 먼저! (여기서 시간이 가장 많이 걸림..ㅋㅋㅋㅋ왜일까.. 의문ㅋㅋㅋㅋ)

                        ↓

인증키 발급 (공공데이터를 사용한다면 인증키가 중요하다.)

                        ↓

> 서울 열린데이터광장

> 지하철호선별 역별 승하차 인원 정보

# 라이브러리 불러오기
import urllib. request
import json
import pandas as pd
# 인증키와 주소
key = '여기에 발급된 인증키 넣기'
start = 1
end = 1000
url = f'http://openapi.seoul.go.kr:8088/{key}/json/CardSubwayStatsNew/{start}/{end}/20230211   # f스트링 사용

# 데이터 가져오기
response = urllib.request.urlopen(url) 
json_str = response.read().decode('utf-8')

# JSON으로 변환(딕셔너리로 변환)
json_object = json.loads(json_str)

# 데이터프레임으로 변환
subway = pd.json_normalize(json_object['CardSubwayStatsNew']['row'])
                                                                   └ JSON 데이터에서 파싱하여 내가 필요한 행을 데이터프레임으로 선언해준 것.
                                                                       파싱: 내가 필요한 행을 추출한다는 뜻.
                                                                        https://jsonformatter.org/json-parser
# 확인
subway.head()

# 데이터 분석(간단한 전처리와 분석을 하고, 시각화를 할 것)

# 시각화를 위한 라이브러리 불러오기
import matplotlib.pyplot as plt

# 한글폰트 지정(맑은 고딕)
plt.rcParams['font.family'] = 'Malgun Gothic'

# 열 정보
subway.info()

# 기초통계정보
subway.describe().T

# 승차 인원이 가장 많은 TOP 10을 추출하여 subway_top 10 데이터프레임을 만들기
subway_top10 = subway.sort_values(by = 'RIDE_PASGR_NUM', ascending = False).head(10)

# 오름차순 ascending (값이 작은 쪽에서부터 큰 쪽으로의 순서) = False 아니다

# 정렬 결과로 어긋난 순서의 인덱스를 깔끔하게 초기화
subway_top10.reset_index(drop=True,inplace=True)
# 호선 승하차 인원 합계를 subway_linesum 데이터프레임으로 만들기
subway_linesum = subway.groupby('LINE_NUM', as_index=False)[['RIDE_PASGR_NUM','ALIGHT_PASGR_NUM']].sum()

# 승차인원 기준으로 내림차순 정렬
subway_linesum = subway_linesum.sort_values(by='RIDE_PASGR_NUM',ascending =False)

# 막대그래프( 계속 손으로 치는 게 답이다! 복사 붙여넣기는 머리에 남는 게 없다!)
plt.figure(figsize = (10,5))                                    ┌ (호선) 표시 ex) 홍대입구(2호선)
plt.bar(x = subway_top10['SUB_STA_NM'] + '(' + subway_top10['LINE_NUM'] + ')', height=subway_top10['RIDE_PASGR_NUM'], data=subway_top10)                                        
plt.xticks(rotation = 45)     # x축 이름 다 보이게 기울기 정도
plt.show()

 

 

> 실습 1. 서울특별시 공공자전거 실시간 대여 정보를 가져오기 #1

 - 호출시 시스템 부하로 한번에 최대 1,000건을 초과할수 없다.
 - 우선 1,000개 행만 조회하세요.

# 라이브러리 불러오기
import urllib. request
import json
import pandas as pd
# 인증키와 주소
key = 'blablabla'
start = 1
end = 1000
url = f'http://openapi.seoul.go.kr:8088/{key}/json/bikeList/{start}/{end}/'

# 데이터 가져오기
response = urllib.request.urlopen(url) 
json_str = response.read().decode('utf-8')

# JSON으로 변환(딕셔너리로 변환)
json_object = json.loads(json_str)

# 데이터프레임으로 변환
bike = pd.json_normalize(json_object['rentBikeStatus']['row'])
                                                              └ JSON 데이터에서 파싱하여 내가 필요한 행을 데이터프레임으로 선언해준 것.
                                                                  파싱: 내가 필요한 행을 추출한다는 뜻. 
                                                                  
https://jsonformatter.org/json-parser
# 상위 데이터 확인
bike.head()

 

> 실습 2. 서울특별시 공공자전거 실시간 대여 정보를 가져오기 #2

- 호출시 시스템 부하로 한번에 최대 1,000건을 초과할수 없다.

- 1,000건이 넘는 데이터를 한꺼번에 가져오자.

- while문을 사용하여 JSON문자열을 연결한 후 이후 과정을 진행한다.

# 강사님께서 푼 방법
# 인증키

key = '어찌구저찌구'
loop = 0
result = []

# 반복해서 가져와 연결하기
while True:
    start = 1 +1000 * loop                                               # 1         1001     2001~~~~n
    end =  1000 + 1000 *loop   # start + 999해도 됨.     # 1000    2000    3000~~~~n
    url = f'http://openapi.seoul.go.kr:8088/{key}/json/bikeList/{start}/{end}/'

    # 데이터 가져오기
    response = urllib.request.urlopen(url) 
    json_str = response.read().decode('utf-8')

    # JSON으로 변환(딕셔너리로 변환)
    json_object = json.loads(json_str)

    result += json_object['rentBikeStatus']['row']

    # 탈출조건???

    if len(result) % 1000 != 0:
        break
    loop += 1
    
    
# 데이터프레임으로 변환
bike = pd.json_normalize(result)

# 상위 데이터 확인
bike.head()
# 또 다른 방법

# 인증키와 주소
loop = 0
result = []
key = '12345678910'
start = 1
end = 1000

# 반복해서 가져와 연결하기
while True:
    start = 1+ loop*1000
    end =  (loop+1)*1000
    url = f'http://openapi.seoul.go.kr:8088/{key}/json/bikeList/{start}/{end}/'

# 데이터 가져오기
    response = urllib.request.urlopen(url) 
    json_str = response.read().decode('utf-8')
    
# JSON으로 변환
    json_object = json.loads(json_str)
    try:
        result += json_object['rentBikeStatus']['row']
        loop += 1
    except:
        break

# 데이터프레임으로 변환
bikes = pd.DataFrame(result)

# 확인
bikes.describe()

 

> 실습 3. 데이터 탐색 및 전처리

# 열 정보
bike.info()

  • 데이터 형식을 int로 변환한다.
  • 대상 열: rackTotCnt, parkingBikeTotCnt, shared
  • 구문 ex) df['Money'].astype('int')
# 데이터 형식 변경  #1

bike['rackTotCnt']= bike['rackTotCnt'].astype('int')
bike['parkingBikeTotCnt'] = bike['parkingBikeTotCnt'].astype('int') 
bike['shared']= bike['shared'].astype('int')

# 데이터 형식 변경 #2

cols = ['rackTotCnt', 'parkingBikeTotCnt', 'shared']
bike[cols]=bike[cols].astype('int')

# 데이터 형식 변경 #3

for col in cols:
    bike[col] = bike[col].astype('int')

 > 참고 : 지도 시각화

위도와 경도 정보가 있으므로 지도상에 거치대 위치를 표시할 수 있다.

# 지도 시각화를 위한 folium 라이브러리 불러오기
!pip install folium

# 라이브러리 불러오기
import folium

# 위 분석에서 거치대가 가장 많은 곳의 좌표를 지도상에 표시
m = folium.Map(location=['37.56133652','126.83390045'], tiles='openstreetmap', zoom_start=17)

# 마커 표시
marker1 = folium.Marker(['37.56133652','126.83390045'],
              popup='LG유플러스 마곡사옥',
              icon=folium.Icon(color='red'))

marker1.add_to(m)

# 확인



# 위 진한 부분이 비어져있었음. 

 

> 공공 데이터 포털

# XML을 딕셔너리 형태로 변환하는 라이브러리 불러오기
# xmltodict 패키지 설치(아나콘다에는 이미 설치 됨)
!pip install xmltodict

 

>  관세청_국가별 수출입실적(GW)

 

# 라이브러리 불러오기
import urllib.request 
import json 
import pandas as pd 
import xmltodict

# 미리보기주소
# https://apis.data.go.kr/1220000/nationtrade/getNationtradeList?serviceKey=인증키&strtYymm=202201&endYymm=202212&cntyCd=US'

# 매개변수
key = ' 일반 인증키 Encoding '
strtYymm = 202201
endYymm = 202212
cntyCd = ' '

# 주소
url = f'http://apis.data.go.kr/1220000/nationtrade/getNationtradeList?serviceKey={key}&strtYymm={strtYymm}&endYymm={endYymm}&cntyCd={cntyCd}'

# 데이터 가져오기
response = urllib.request.urlopen(url) 

# xml --> dict
xml_parse = xmltodict.parse(response)
xml_dict = json.loads(json.dumps(xml_parse))

result = xml_dict['response']['body']['items']['item']  # 데이터 부분 딕셔너리 키 확인 필요

# 데이터프레임으로 변환
im_export = pd.json_normalize(result)

# 확인
im_export
  • Pandas는 숫자가 크면 숫자를 2.805000e+03 형태로 표시합니다.
  • 가독성을 높이기 위해 이후 숫자 출력은 소수점 두자리를 갖는 일반 형태로 표시하게 합니다.
# 소수점 네 자리까지표시
pd.set_option('display.float_format', lambda x: '%.4f' % x)
  • 이후 수치 비교를 위해 숫자 데이터를 int64로 변환.
  • 대상 열: balPayments, expCnt, expDlr, impCnt, impDlr
  • 구문 ex) df['Money'].astype('int64')
# 데이터 형식 변환

cols = ['balPayments', 'expCnt', 'expDlr', 'impCnt', 'impDlr']
im_export[cols] = im_export[cols].astype('int64')
  • 2022년 12월 데이터를 별도로 추출하여 im_export12 데이터프레임을 만듭니다.
  • 무역수지(balPayments)를 기준으로 내림차순 정렬합니다.
  • 정렬 결과로 어긋난 순서의 인덱스를 깔끔하게 초기화합니다.
  • 상위 10개 행만 출력해 2022년 12월 무역수지 TOP 10을 확인합니다.
# 내가 출력한 답
# 2022년 12월 무역수지 TOP 10

# im_export12 = im_export.loc[im_export['year']=='    ']                    << 이부분은 생각도 못함.
# im_export12.sort_values(by='balPayments', ascending = False)    << 여기서 잘못했잖아!!
# im_export12.reset_index(drop = True , inplace = True)
# im_export12.head(10)

# 정답
# 2022년 12월 무역수지 TOP 10
im_export12 = im_export.loc[im_export['year'] == '2022.12',]
im_export12 = im_export12.sort_values(by='balPayments', ascending = False)
im_export12.reset_index(drop=True, inplace=True)
im_export12.head(10)

 

 

 

 


블로그 정보가 부족하면

[파이썬] 서울 공공데이터 포털 Open API를 이용해서 지하철 승차인원수 구하기 | Exobrain (gunn.kim)

[python] 공공 데이터 포털 API 불러오기 — 코딩하는 감자 (tistory.com)

이쪽에서 정보를 얻는 것이 좋을 것 같다. 나도 이쪽에서 수업에 필요한 정보를 얻었다.

 

 반복이 제일 중요한 것 같다.  코드를 손에 익히는 느낌이랄까? 내림차순 정렬! 나오면 바로 .sort_values(by = ' ', ascending = False)가 내 손에서 나오도록 연습하는 게 중요하다고 한다. 강사님께서도 복사 붙여넣기는 본인만 하는 것이라고 하실만큼 반복이 중요하다는 것을 항상 생각하자.

 

'KT AIVLE School 3기 > Pandas' 카테고리의 다른 글

KT Aivle DX 트랙 20일차  (0) 2023.02.28
KT Aivle DX트랙 19일차  (0) 2023.02.27
KT Aivle DX 트랙 17일차  (0) 2023.02.23
KT Aivle DX 트랙 16일차  (0) 2023.02.22
KT Alive DX 트랙 15일차  (0) 2023.02.22