본문 바로가기

Programming/Data mining

4. pandas 기초(series, dataframe)

Coursera.org 에서 Michigan University의 Applied Data Science with Python의 강의를 토대로 정리한 내용입니다.

오늘은 파이썬을 활용한 데이터분석 3대장 라이브러리 중 하나인 pandas에 대해서 알아보도록 할게요.
3대장 중 하나는 저번시간에 다뤘던 Numpy이구요? 나머지 하나는 아마 곧 다루게 될 거에요.
pandas는 특히 숫자 테이블이나 시계열 분석을 위한 데이터 구조 및 함수들을 제공하는데요. 
한번 시작해보죠.

import pandas as pd #pandas는 주로 이렇게 import 한답니다.

animals = ['Tiger', 'Bear', 'Moose']
pd.Series(animals)
>>>
0    Tiger
1     Bear
2    Moose
dtype: object


#이렇게 하나의 리스트를 .Series() 함수를 통해서 pandas의 series라는 데이터 타입으로 저장하였는데요.
#index가 존재하는 1차원의 배열이라고 생각하면 될 것 같네요. 

sports = {'Archery': 'Bhutan',
          'Golf': 'Scotland',
          'Sumo': 'Japan',
          'Taekwondo': 'South Korea'}
s = pd.Series(sports)
>>>
Archery           Bhutan
Golf            Scotland
Sumo               Japan
Taekwondo    South Korea
dtype: object

#위처럼 하나의 dictionary를 series화 하니, index가 기존의 dictionary구조의 key값들로 채워지네요.

sports = {'Archery': 'Bhutan',
          'Golf': 'Scotland',
          'Sumo': 'Japan',
          'Taekwondo': 'South Korea'}
s = pd.Series(sports, index=['Golf', 'Sumo', 'Hockey'])
>>>
Golf      Scotland
Sumo         Japan
Hockey         NaN
dtype: object

# 그리고 이처럼 직접 index를 설정해줄 수도 있습니다. 이때 설정된 index에 대응되는 값만이 저장됨을 알 수 있는데요.
# 만약 해당 index에 대응되는 값이 없다면 NAN으로 나타난다는 것 기억해주세요. 이 NAN 값들은
import numpy as np
np.isnan(np.nan) # numpy의 .isnan() 함수를 통해서 검정할 수 있답니다.

# 그러면 이제 위에 s에 저장된 값들은 어떻게 불러올 수 있을까요? 
# 이를 우리는 querying 한다고도 말할 수 있어요. 쿼리란? 쉽게 말해 데이터베이스에 요청을 해 정보를 얻는 구조에요.

s.iloc[1] >>> Japan #이처럼 직접 인덱스의 위치를 물어볼 수도 있구요.
s.loc[Golf] >>> Scotland #이처럼 직접 인덱스 정보로 물어볼 수도 있답니다.

#이를 활용하여 아래와 같은 데이터 추가도 가능하고요.
s = pd.Series([1, 2, 3])
s.loc['Animal'] = 'Bears'
>>>
0             1
1             2
2             3
Animal    Bears
dtype: object

#아래처럼 .append()함수를 활용하기도 하네요.
original_sports = pd.Series({'Archery': 'Bhutan',
                             'Golf': 'Scotland',
                             'Sumo': 'Japan',
                             'Taekwondo': 'South Korea'})
cricket_loving_countries = pd.Series(['Australia',
                                      'Barbados',
                                      'Pakistan',
                                      'England'], 
                                   index=['Cricket',
                                          'Cricket',
                                          'Cricket',
                                          'Cricket'])
all_countries = original_sports.append(cricket_loving_countries)
>>>
Archery           Bhutan
Golf            Scotland
Sumo               Japan
Taekwondo    South Korea
Cricket        Australia
Cricket         Barbados
Cricket         Pakistan
Cricket          England
dtype: object

 

이렇게 pandas에서 series 를 활용한 데이터 정리 및 쿼링을 알아보았는데요.
하지만 현실에 존재하는 거의 모든 데이터들은 이렇게 1차원의 배열로 구성되기 보다는 테이블 형태로 존재하죠?
그럴 때 사용하는 pandas의 데이터타입이 바로 dataframe입니다!

#먼저 아래처럼 세개의 series들을 정의하고, 이들을 하나의 데이터 프레임에 넣을 수 있어요.
#
purchase_1 = pd.Series({'Name': 'Chris',
                        'Item Purchased': 'Dog Food',
                        'Cost': 22.50})
purchase_2 = pd.Series({'Name': 'Kevyn',
                        'Item Purchased': 'Kitty Litter',
                        'Cost': 2.50})
purchase_3 = pd.Series({'Name': 'Vinod',
                        'Item Purchased': 'Bird Seed',
                        'Cost': 5.00})
df = pd.DataFrame([purchase_1, purchase_2, purchase_3], index=['Store 1', 'Store 1', 'Store 2'])
>>>
	   Cost	Item Purchased	Name
Store 1	22.5	Dog Food	Chris
Store 1	2.5	Kitty Litter	Kevyn
Store 2	5.0	Bird Seed	Vinod

#이를 통해서 우리는 각각의 series들이 dataframe의 한 행이나 한 열들의 type이겠구나를 알 수 있겠네요.

#추가적으로 dataframe을 querying할 때는 어떻게 할 수 있을까요?
df.loc['Store 1'] # 마찬가지로 이렇게 하면 'Store 1'에 해당되는 데이터가 출력된답니다.
>>>
		Cost	Item Purchased	Name
Store 1	22.5	Dog Food	Chris
Store 1	2.5	Kitty Litter	Kevyn

#그렇다면 이중에서도 column을 선택하고 싶을 때는요?
df.loc['Store 1', 'Cost'] #이렇게 설정해준답니다.
>>>
Store 1    22.5
Store 1     2.5
Name: Cost, dtype: float64

df.loc['Store 1']['Cost']
#그렇다면 이 방법은 어떨까요? 역시나 위와 같은 결과가 출력된답니다.
#하지만 이런식의 indexing을 chaning이라고 하는데요.
#이런 chaining 방법은 자칫 주소 복사가 일어나게 되서 예상치 못한 결과를 나을 수도 있어요!(안쓰는걸 추천)

df.loc[:,['Name', 'Cost']]
>>>
		Name	Cost
Store 1	Chris	22.5
Store 1	Kevyn	2.5
Store 2	Vinod	5.0
# 그리고 여러 항목을 indexing하기 위해선 위와 같이 호출할 수 있겠군요. 
# 혹시 :과 같은 마크가 이해가지 않는다면 점프투파이썬의 list편을 보고 오세요 :)

df['Cost']
>>>
Store 1    22.5
Store 1     2.5
Store 2     5.0
Name: Cost, dtype: float64
#위와 같이 loc이나 iloc이 아닌 column의 index를 호출하여 column을 호출할 수도 있답니다.

 

자 이렇게, series와 dataframe에 대한 개념과 각각 indexing이 어떻게 일어나는 지 알아보았는데요.
그러면 이러한 데이터구조들이 지원하는 기능은 어떤 게 있을까요?
사실 이번 편에서 다루기에는 너무 방대한 부분이 있으니 차차 알아가기로 하고, 궁금한 점들은 공식 documentation이나 Stack overflow혹은 구글링을 통해서 능동적으로 알아보는 걸 추천드립니다.
우선 간단한 소개만 드리고 이번 챕터는 끝내도록 할게요.

df.drop('Store 1', inplace = False) 
#df의 'store 1'이라는 index를 가진 series들의 정보를 drop합니다.
#inplace는 True로 설정 시 drop한 채로 값이 설정되구요, False 설정 시 실제 drop은 진행되지 않습니다.

df['Cost'].count()
#열이나 행의 element들의 갯수를 반환합니다.

costs = df['Cost']
#이렇게 각 series들을 변수로 할당해줄 수 있는데 이때 주소복사가 일어나게 됩니다. 따라서
costs += 2 #의 결과는 costs series뿐 아니라 df의 'Cost' column의 값들도 2가 더해지는 결과가 나타나죠.

df = pd.read_csv('olympics.csv')
#이런식으로 csv나 다른 데이터형식의 파일들을 pandas로 불러올 수 있는데,
#이 때 table형태라면, dataframe형식으로 저장되겠죠?
#아래처럼 index_col을 통해서 index로 사용할 columns과 불필요한 데이터들을 skiprows를 통해 설정할 수 있습니다.
df = pd.read_csv('olympics.csv', index_col = 0, skiprows=1)
df.columns #이는 df의 columns의 index들을 list형태로 반환합니다.

for col in df.columns:
    if col[:2]=='01':
        df.rename(columns={col:'Gold' + col[4:]}, inplace=True)
#이런 식으로 column의 이름을 변경할 수도 있습니다.
#실제 데이터를 볼 수 없으니 간단히 설명드리자면, df의 column의 index가 01로 시작하면
#df의 columns에서 해당 col의 이름을 'Gold' + col[4:]로 변환한다는 의미입니다. 
#아마 올림픽 금메달에 관한 데이터겠네요.