본 포스팅은 2022-09-14(수), 국민대학교 허대영 교수님의 소프트웨어융합최신기술 수업을 통해 배운내용을 정리하기 위해 작성하는 게시글입니다.
# 시작하며
오늘 수업에서 최종 결과물로는 위 시각화 자료를 만드는 실습을 해봤다. 지금껏 전공수업에서는 이해하기위해서 안간힘을 썼는데, 이번 수업은 그렇지 않아서 나름 힐링 됐다. 수업 중에 실습했던 내용들을 바탕으로 궁금했던 것들을 하나씩 공부해보면서 정리하는 시간을 가지도록 하겠다.
# 라이브러리 사용
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
판다스, 넘파이, 팻플롯립을 임포트해줘야 한다. 각 라이브러리의 기능을 잠깐 알아보자면,
## pandas
시리즈 및 데이터프레임을 사용할 수 있으며, csv파일을 읽을 수 있는 등 데이터들을 알맞게 처리하고 분석하는데 유용하다.
## numpy
행렬 및 배열 처리에 관한 연산을 numpy의 array를 이용해서 매우 빠르고 효율적이게 진행 할 수 있다. 특히 numpy자체적으로 지원하는 행렬/배열에 관한 함수들을 사용하면 코드를 많이 사용할 일이 없다.
## matplotlib
시각화 자료를 만드는데 사용한다.
# 데이터 셋 만들기
위 웹사이트에서 첫행을 제외한 자료를 복사하여, 쥬피터 노트북에 아래와 같이 붙여넣어준다.
data = """1 - The Black Phone $333,411 - 425 - $784 $598,732 1 Universal Pictures International (UPI)
2 4 Nope $41,675 -78.2% 34 -237 $1,225 $3,493,312 4 Walt Disney Studios Motion Pictures
3 6 Minions: The Rise of Gru $9,112 -91% 23 -206 $396 $16,809,510 8 Universal Pictures
4 21 The Northman $5,900 -13.1% 18 -14 $327 $31,416 2 Universal Pictures International (UPI)
5 24 Thor: Love and Thunder $125 -93.9% - - - $22,608,225 10 Walt Disney Studios Motion Pictures"""
붙여넣은 자료는 "\t"과 "\n"으로 구분되어지고 있는 것을 알 수 있다. 이 정보를 바탕으로, 5행과 11열로 나누어진 array자료형을 얻어내야 한다.
movies = np.array(data.split('\n')) # 5행의 정보를 numpy배열로 바꾸기
movies = np.char.split(movies,sep="\t") # array와 list에 주의,그래서 numpy 2차원배열로 바꿔줘야함
movies.shape
# OUTPUT : (5,)
이렇게 하면 각 행과 열로 구분되어지게 split될 것 같지만, OUTPUT에서 보이는거와 같이 열에 대한 정보가 없음을 알 수 있다. movies를 보게 되면 각 array안에는 list가 5개 들어가 있는 형태임을 알 수 있다. 즉 numpy는 이 데이터를 array( list, list, list, list, list )처럼 읽고 있는 것이다.
array 2차원 배열의 형태로 변환 후 pandas의 dataFrame으로 변환하는 작업을 거쳐준다.
movies.tolist() # 2차원 파이썬 리스트로 바뀜
movies = np.array(movies.tolist())
movies.shape # 2차원 numpy 행렬로 변환 성공
df = pd.DataFrame(movies) # 판다스가 빠르기 때문에 바꿔줌
df
다음과 같이 출력 됨을 알 수 있다. 그러나 각 열 정보를 담고 있는 첫행이 0,1,2,3,4,5,6,7,8,9,10으로 표기되어 각각의 자료가 무엇을 담고 있는지 알 수 없기 때문에 열 정보를 알 수 있도록 데이터를 정리해주자.
title="Rank\tLW Release Gross %± LW Theaters Change Average Total Gross Weeks Distributor"
columns = title.split("\t")
df.columns = columns
print(df.columns)
웹사이트에서 첫 행을 긁어 title변수에 담아준 후, 데이터를 "\t"을 기준으로 split한 후, df의 columns속성에 연결지어 주자. 이후 df를 확인해보면 아래와 같다.
이제 데이터를 시각화하기 위한 자료를 dataFrame에 알맞은 형태로 얼추 정리했다. 이번 수업에서는 Gross라는 데이터를 통해서 영화의 한주 수입을 분석했다. 그러기 위해서는 Gross데이터를 변환해주는 과정을 거쳐야 한다.
# 데이터 셋 가공하기
먼저 데이터프레임에 있는 각 시리즈(열 데이터)들이 어떤 types을 가지고 있는지 확인해주자.
df.dtypes # 값들이 숫자이어야한다. 꼭 확인해야함, Rank는 의미론적으로 해석하면 이산형이기때문에 숫자든 문자든 똑같음
df["Gross"]
Gross는 object타입이기 때문에 정수(Int64)형태로 변환되어야함과 동시에 그러기 위해서는 $123,456과 같은 달러($)와 쉼표(,)를 없애주어야 한다.
간단히 파이썬에서 쓰던 replace를 사용해서 변환 할 수 있다.
df["Gross"] = df["Gross"].str.replace("$","") # $와 , 를 없애야함
df["Gross"] = df["Gross"].str.replace(",","") # $와 , 를 없애야함
df["Gross"]
아직 type은 object이기 때문에 정수형으로 바꿔주도록 하자. 판다스의 to_numeric을 사용하면 해당 시리즈에 대해서 일괄적으로 변환이 가능하다.
df["Gross"] = pd.to_numeric(df["Gross"]) # 숫자형태로 바꿔줌, 시리즈에 대해서 일괄적으로 적용해줌
df.dtypes
아래 두가지는 큰 차이가 있다.
# 첫번째 방식
df["Gross"]
# 두번째 방식
df[["Gross"]]
첫번재 방식은 그냥 시리얼이 뽑혀나오고, 두번째 방식은 데이터프레임이 뽑혀나온다.
이제 시각화 전 마지막 단계로, 영화명과 Gross만을 가지는 새로운 DataFrame을 만들어 보자.
df[ ["Release","Gross"] ]
# temp = df[ ["Release","Gross"] ]
# temp.shape
위와 같이 봅아내면 ( 인덱스,시리얼,시리얼 )의 데이터프레임이 형성되지만, 이게 아닌 인덱스로써 역할을 하도록 해주자.
grossDf = df[["Gross"]].set_index(df["Release"])
grossDf
grossDf.dtypes
grossDf.shape
# 시각화 하기
현재 만든 grossDf를 활용해서 시각화를 해보고 문제점을 찾아보자.
grossDf.plot(kind='bar')
plt.show()
한눈에 보기 쉬운가?! 난 당연히 아니다. 뭐가 문제일까?!
- x축의 영화명들이 90도 회전된 상태라 읽기 어려움
- 각각의 Gross수치의 편차가 너무 큰 나머지 첫번째 데이터를 제외한 나머지 데이터들을 파악하기 어려움
한 데이터만 매우 크다보니까 나머지 데이터들을 파악하기 어렵다. 로그스케일로 변환시켜보자.
grossDf.plot(kind='bar',logy=True) # 로그 스케일로 바꿔줌, 각각의 눈금크기(단위)가 달라지기에 주의해야함
plt.show()
단, 로그스케일은 각 눈금이 나타내는 것이 일정하지 않고 제곱승으로 늘어나기 때문에 보이는 막대들의 크기로 실제 데이터의 크기라고 오해하면 안된다. 데이터를 시각화 할때는 이 점에 꼭 유의하라고 당부하셨다.
y범례(라벨)값을 추가적으로 달아주고, 단위를 표현해야한다. 숫자에 단위가 없다면 해석에 큰 오해가 있을 수 있기 때문이다.
grossDf.plot(kind='bar',logy=True,ylabel="Weekend / Earning(USD)")
plt.show()
이제, x축이 90도 회전되어 있는걸 해결해야한다. 저걸 바로 30도의 값으로 회전시켜준다면 과연 보기 편할까?
grossDf.plot(kind='bar',logy=True,ylabel="Weekend / Earning(USD)",rot=30) # rot를 바꿔주기는 하지만 여전히 보기 좋지 않음
plt.show()
어찌어찌 보기 쉬운거 같지만, Minions: The Rise of Gru와 The Nortman 두개가 서로 영역을 침범해 얼핏보면 오해의 소지를 불러 일으킬 수 있다. 이것은 좋은 시각화가 아니라고 하셨다.
barh의 종류는 bar의 수평형태라고 한다.
grossDf.plot(kind="barh",logx=True) # barh(orizental) 수평형태로 바꿔줌
plt.xlabel("Weekend / Earning(USD)")
plt.show()
보기 매우 편해졌다!
한가지 아쉬운점이 있다면 큰 자료를 위에서부터 보여주고 싶다. ascending속성을 사용해서 값들을 정렬시킨 후 시각화를 해보자.
grossDf.sort_values(by="Gross",ascending=True).plot(kind="barh",logx=True) # 내림차순을 오름차순으로 바꾸고 그래프를 그려줌
plt.xlabel("Weekend / Earning(USD)") # 그러나 자체적으로 순서가 있는 자료이면 정렬을 하면 안됨
plt.show()
보기 쉬운 데이터로 시각화가 끝났다!
# 마치며
생각보다 재밌는 오늘의 수업이었다. 그러나 아직 dataFrame에 확실한 이해가 없는거 같고 판다스,넘파이등의 많은 기능을 잘 모르고 있어서 내가 원하는것으로 딱딱 바꾸지는 못할것 같다.
그리고 오늘 인공지능, 컴퓨터비전, 소용최기 수업을 들으면서 드는 생각은 선형대수와 행렬을 매우매우 중요하다는 걸 알았다... ㅠㅠ