본격 Pandas 잡아먹기
1편: Pandas.Series
데이터 사이언스와 Pandas
데이터 사이언스의 목표야 다들 아시다 싶이 데이터에서 유의미한 결과를 뽑아내고 그를 통해 가치를 창출하는 것이겠죠.
목표를 이루기 위해서 대개 아래와 같은 과정을 거칩니다.
- 데이터 수집
- 데이터 전처리
- 모델 구성 및 학습
- 모델 검증
- 적용
위 과정 중 데이터를 다루는 사람의 입장에서 가장 짜증나고 손이 많이 가는 일이 뭘까요?
사람마다 다르겠지만 저는 다루고자 하는 데이터를 수집하고 모델에 집어넣기까지 만지작 거리는 구간이 가장 힘들고 손이 많이 간다고 생각합니다.
데이터 수집이야 대부분이 직접 할 수 없고, 배우는 입장에서는 이미 수집된 데이터를 가져다 쓴다고 쳐도, 전처리는 모두가 겪어야 하는 시련과 같은 구간이죠.
적은 양의 데이터야 뭐 엑셀로 처리한다고 해도, 수십만개의 엔트리를 가지는 데이터는 무거운 엑셀로 처리하자면 고생이 이만 저만이 아니죠.
Python의 Datascience 라이브러리는 이 부분을 훌륭하게 도와줄 수 있습니다.
(Pandas = 엑셀의 파이썬 대용품이라고 생각하고 접근해봅시다.)
이 노트북 시리즈에서는 Pandas의 기초를 간단히 다지고 그를 기반으로 작은 토이 데이터를 만지작거리는 작업을 함께 해보도록 할게요.
Pandas의 Series
Pandas의 기본 데이터 구조
Pandas는 기본적으로 두 레벨의 기본 데이터 구조를 갖고 있어요.
- Series
- Dataframe
Series는 기본적으로 1차원 형태의 데이터이고, Dataframe는 여러 Series가 합쳐진 형태의 2차원 데이터 구조에요.
Series를 엑셀 파일에 펼쳐진 데이터시트의 각 열(Column), Dataframe을 해당 데이터 시트라고 생각하면 편해요.
이번 노트북에서는 Series 데이터 구조를 살펴봅시다.
본격적으로 들어가기 전에, Pandas와 Numpy를 import 해 줍시다.
# pandas / numpy 임포트
import pandas as pd
import numpy as np
Series 생성하기
pandas.Series 데이터 구조는 여러가지 다른 데이터 구조에서부터 생성될 수 있어요.
- List
- Array
- Dict
- Scalar
# Series 만들기
#pd.Series?
'''
pd.Series(*args, **kwargs)
Init signature: pd.Series(*args, **kwargs)
Parameters
----------
data : array-like, Iterable, dict, or scalar value
Contains data stored in Series.
=> Series 생성 함수에는 data가 들어가고, data는 Array, Iterable, Dict, scalar 형식이 될 수 있다.
'''
## List애서 만들기
s1 = pd.Series([10,20,30,40,50])
## Scalar에서 만들기
s2 = pd.Series(10, index=['a','b','c'])
## Dictionary에서 만들기
s3 = pd.Series({'1번':10, '2번':20})
## numpy array에서 만들기
s4 = pd.Series(np.arange(10,60,10))
## Series에는 자동으로 Index(Label)이 붙는걸 확인할 수 있다.
print(s1)
print(s2)
print(s3)
print(s4)
## Series 생성은 편하게 하고 싶은대로 하면 된다.
Series의 성질
Pandas Series는 기본적으로 numpy array와 매우 비슷하게 동작하며 동시에 dictionary 자료형과도 비슷하게 작동해요.
마치.. 각 값에 키값이 붙어있는 numpy array라고나 할까요?
numpy와 파이썬 dictionary를 다뤄봤던 사람이라면 그래서 쉽게 받아들일 수 있어요.
# numpy array <-> pandase Series
ndarray = np.arange(10,100,10)
s_np = pd.Series(ndarray)
print('data:\n',ndarray)
## numpy array에서 series 생성
print('Series:\n',s_np)
## Series를 다시 numpy array로 변환
print('Back to array:\n', s_np.to_numpy())
# numpy 처럼 조작 가능
## 인덱스로 접근
print(s_np[3])
## 조건부 인덱싱
print(s_np[s_np>=30])
## 멀티 인덱싱
print(s_np[[5,3,1]])
## 각 원소값에 메서드 적용
print(np.exp(s_np))
## dtype 추출
print(s_np.dtype)
# Dictionary 처럼 조작 가능!
data_dict = {'1번':10, '2번':20, '3번':30}
s_dict = pd.Series(data_dict)
print(s_dict)
## 키값으로 접근
print(s_dict['2번'])
Series와 Numpy array와의 차이점?
앞서 살펴보니 Series랑 numpy array간에는 공통점이 많네요.
심지어 numpy array에 적용되는 많은 메소드들이 pandas series에도 공통 적용될 수 있다는 것을 확인할 수 있었어요.
그렇다면 둘 사이에는 어떤 차이점이 있을까요?
자동 레이블 정렬
위에서 pandas Series를 생성하면 자동으로 label이 붙는다는 것을 보았죠.
그리고 이것이 바로 둘 사이의 가장 큰 차이점을 만듭니다.
Pandas Series는 series 사이에 연산이 일어나도 여전히 각 원소 값에 해당하는 label에 따라 정렬된 값 사이에서 연산이 일어나요!
자세히 살펴볼까요?
# array와 series 생성
n1 = np.arange(10,100,10)
n2 = np.arange(100,1000,100)
s1 = pd.Series(n1)
s2 = pd.Series(n2)
print(n1,n2)
print(s1,s2) # pandas series에는 가장 좌측열에 label이 추가됨에 주목!
# 같은 연산, 다른 결괴
n3 = n1[:8] + n2[1:]
s3 = s1[:8] + s2[1:]
print(n3)
print(s3) # 차이점에 주목하세요!
위 결과에서 알 수 있듯, numpy array는 indexing([:8], [1:]) 된 결과 값이 각자 새로운 array처럼 새로 인덱스를 받고 결합되지만,
pandas Series는 여전히 label을 가지고, label이 같은 것들 끼리만 정렬되어 계산된답니다.
Series는 이름도 가질 수 있다.
pandas series에는 각자를 지칭하는 이름 속성도 부여할 수 있어요.
index = ['월','화','수','목','금','토','일']
working_hours = pd.Series([6,6,8,4,2,4,0], index=index, name="근무시간")
wage_per_hours = pd.Series(15000, index=index, name="시급")
print(working_hours)
print(wage_per_hours)
## rename 메소드로 이름 속성을 변경할 수 있어요!
income_per_day = (working_hours * wage_per_hours).rename("요일별 수입")
print(income_per_day)
마치며 + 요약
pandas 잡아먹기 첫 시리즈로 pandas의 가장 기본이 되는 데이터 구조인 pandas.Series에 대해 살펴보았어요.
아주 많은 것을 다루지는 않았지만 아래 내용은 꼭 알고 가면 좋을 것 같아요.
- Pandas Series는 엑셀 데이터 시트의 열(colum)과 같은 의미의 1차원 데이터를 표상한다.
- Series의 각 원소는 자동으로 label을 index로 가지게 되며 이에 따라 자동 정렬 연산된다.
- Series는 numpy array나 dictionary 처럼 서로 연산하거나 키를 통해 접근이 가능하다.
- Series 데이터 구조에는 name 속성도 지정 가능하다!