pandas 소개 1

자료 μ•ˆλ‚΄: pandas 라이브러리 νŠœν† λ¦¬μ–Όμ— μžˆλŠ” Lessons for new pandas users의 01-Lesson λ‚΄μš©μ„ λ‹΄κ³  μžˆλ‹€.

In [3]:
# pandas λͺ¨λ“ˆμ—μ„œ DataFrame ν•¨μˆ˜μ™€ read_csv ν•¨μˆ˜ μž„ν¬νŠΈ
from pandas import DataFrame, read_csv

# matplolib.pyplot λͺ¨λ“ˆκ³Ό pandas λͺ¨λ“ˆμ„ 각각 plt와 pdλΌλŠ” λ³„μΉ­μœΌλ‘œ μž„ν¬νŠΈ
import matplotlib.pyplot as plt
import pandas as pd
In [4]:
# μ₯¬ν”Όν„° λ…ΈνŠΈλΆμ—μ„œ κ·Έλž˜ν”„λ₯Ό 직접 λ‚˜νƒ€λ‚΄κΈ° μœ„ν•΄ μ‚¬μš©ν•˜λŠ” μ½”λ“œ
# 파이썬 μ „λ¬Έ μ—λ””ν„°μ—μ„œλŠ” μ‚¬μš©ν•˜μ§€ μ•ŠμŒ
%matplotlib inline

데이터 생성

1880년에 νƒœμ–΄λ‚œ 아이듀 μ€‘μ—μ„œ κ°€μž₯ 많이 μ‚¬μš©λ˜λŠ” 5개의 이름을 담은 리슀트 names와 ν•΄λ‹Ή μ΄λ¦„μœΌλ‘œ μΆœμƒμ‹ κ³ λœ μ•„μ΄λ“€μ˜ 숫자λ₯Ό 담은 데이터 birthsκ°€ λ‹€μŒκ³Ό κ°™λ‹€.

In [5]:
# 아이 이름과 μΆœμƒμ‹ κ³  숫자 리슀트
names = ['Bob', 'Jessica', 'Mary', 'John', 'Mel']
births = [968, 155, 77, 578, 973]

두 개의 리슀트λ₯Ό ν•©ν•˜μ—¬ 이름과 숫자λ₯Ό 쌍으둜 λ¬ΆκΈ° μœ„ν•΄μ„œ zip ν•¨μˆ˜λ₯Ό μ΄μš©ν•œλ‹€.

  • zip ν•¨μˆ˜μ˜ 리턴값은 zip 클래슀의 객체이닀.
    • zip κ°μ²΄λŠ” μˆœμ„œμŒλ“€μ˜ λ¦¬μŠ€νŠΈμ™€ λΉ„μŠ·ν•˜λ‹€.
    • λ‹€λ§Œ 리슀트처럼 색인을 μ‚¬μš©ν•˜μ—¬ 직접 ν•­λͺ©μ„ 선택할 μˆ˜λŠ” μ—†λ‹€.
  • zip κ°μ²΄λŠ” iterable μžλ£Œν˜•μ΄λ‹€. 즉, 예λ₯Ό λ“€μ–΄ for 반볡문과 ν•¨κ»˜ μ‚¬μš©ν•˜μ—¬ 각 ν•­λͺ©μ„ μˆœμ„œλŒ€λ‘œ ν™œμš©ν•  수 μžˆλ‹€.
In [19]:
for item in zip(names, births):
    name, num = item
    print(name, "μ΄λ¦„μœΌλ‘œ",num, "λͺ…이 μ‹ κ³ λ˜μ—ˆλ‹€.")        
Bob μ΄λ¦„μœΌλ‘œ 968 λͺ…이 μ‹ κ³ λ˜μ—ˆλ‹€.
Jessica μ΄λ¦„μœΌλ‘œ 155 λͺ…이 μ‹ κ³ λ˜μ—ˆλ‹€.
Mary μ΄λ¦„μœΌλ‘œ 77 λͺ…이 μ‹ κ³ λ˜μ—ˆλ‹€.
John μ΄λ¦„μœΌλ‘œ 578 λͺ…이 μ‹ κ³ λ˜μ—ˆλ‹€.
Mel μ΄λ¦„μœΌλ‘œ 973 λͺ…이 μ‹ κ³ λ˜μ—ˆλ‹€.
  • zip 객체λ₯Ό 리슀트 μžλ£Œν˜•μœΌλ‘œ ν˜•λ³€ν™˜μ„ ν•˜λ©΄ μŒλ“€μ˜ 리슀트둜 ν™œμš©ν•  수 있으며, μ—¬κΈ°μ„œλŠ” 이 κΈ°λŠ₯을 ν™œμš©ν•œλ‹€.
In [21]:
BabyDataSet = list(zip(names, births))
print(BabyDataSet)
[('Bob', 968), ('Jessica', 155), ('Mary', 77), ('John', 578), ('Mel', 973)]

주의: zip ν•¨μˆ˜μ— λŒ€ν•œ μ •λ³΄λŠ” μ•„λž˜ λͺ…λ ΉμœΌλ‘œ 확인할 수 μžˆλ‹€.

help(zip)

zip을 ν™œμš©ν•˜μ—¬ 이름과 숫자λ₯Ό μ„œλ‘œ 쌍으둜 λ¬Άμ—ˆλ‹€. ν•˜μ§€λ§Œ 데이터 뢄석을 μœ„ν•΄μ„œλŠ” pandas λͺ¨λ“ˆμ—μ„œ 데이터 ν”„λ ˆμž„(DataFrame) 객체λ₯Ό μ΄μš©ν•˜λŠ” 것이 보닀 μœ μš©ν•˜λ‹€.

BabyDataSet을 데이터 ν”„λ ˆμž„ 객체둜 λ³€ν˜•ν•˜λ©΄ μ—‘μ…€ νŒŒμΌμ— μ‚¬μš©λ˜λŠ” μŠ€ν”„λ ˆμŠ€μ‰¬νŠΈ(spreadsheet)와 같은 ν‘œκ°€ λœλ‹€.

In [5]:
df = pd.DataFrame(data = BabyDataSet, columns = ['Names', 'Births'])

df에 μ €μž₯된 데이터 ν”„λ ˆμž„μ„ ν™•μΈν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

  • columns에 μ‚¬μš©λœ Names와 Birthsκ°€ 각 μ—΄μ˜ ν•­λͺ©μ΄λ¦„μœΌλ‘œ μ§€μ •λœ 것을 확인할 수 μžˆλ‹€.
  • 첫재 쀄은 λ”°λΌμ„œ 헀더(header)라고 λΆˆλ¦°λ‹€.
  • λ°˜λ©΄μ— 첫째 열은 μžλ™μœΌλ‘œ 쀄 λ²ˆν˜Έκ°€ μƒμ„±λ˜λ©° 색인(index)이라고 λΆ€λ₯Έλ‹€.
In [6]:
df
Out[6]:
Names Births
0 Bob 968
1 Jessica 155
2 Mary 77
3 John 578
4 Mel 973

이 데이터 ν”„λ ˆμž„μ„ births 1880.csvλΌλŠ” μ΄λ¦„μ˜ csv 파일둜 μ €μž₯ν•΄λ³΄μž. 데이터 ν”„λ ˆμž„ 객체에 ν¬ν•¨λœ to_csv λ©”μ†Œλ“œλŠ” 데이터 ν”„λ ˆμž„ 객체λ₯Ό csv 파일둜 λ³€ν™˜ ν›„ μ €μž₯ν•œλ‹€. μ €μž₯ μœ„μΉ˜λŠ” 데이터 ν”„λ ˆμž„ 객체와 λ™μΌν•œ 디렉토리이닀. λ¨Όμ € μ•„λž˜ λͺ…λ ΉμœΌλ‘œ to_csv λ©”μ†Œλ“œμ— λŒ€ν•΄ 정보λ₯Ό ν™•μΈν•˜λŠ” 것을 ꢌμž₯ν•œλ‹€.

help(df.to_csv)

to_csv λ©”μ†Œλ“œλŠ” μ €μž₯λ˜λŠ” 파일의 이름 이외에 index와 headerλΌλŠ” 두 개의 ν‚€μ›Œλ“œ 인자λ₯Ό 더 μ‚¬μš©ν•œλ‹€. 각각 색인과 헀더 ν•­λͺ©μ„ ν•¨κ»˜ μ‚¬μš©ν•  것인지 μ—¬λΆ€λ₯Ό κ²°μ •ν•œλ‹€.

In [7]:
df.to_csv('births1880.csv', index = False, header = False)

데이터 호출

csv νŒŒμΌμ„ 뢈러였기 μœ„ν•΄, pandas λͺ¨λ“ˆμ˜ read_csv ν•¨μˆ˜λ₯Ό μ΄μš©ν•œλ‹€. read_csv ν•¨μˆ˜λ₯Ό μ‚΄νŽ΄λ³΄μž.

help(read_csv)

read_csv ν•¨μˆ˜λŠ” λ§Žμ€ μΈμžλ“€μ„ 받을 수 μžˆμ§€λ§Œ μ—¬κΈ°μ„œ μš°λ¦¬λŠ” csv 파일의 μœ„μΉ˜λ§Œ μ‚¬μš©ν•œλ‹€. λ‚˜λ¨Έμ§€ μΈμžλŠ” ν‚€μ›Œλ“œ 인자둜 μ§€μ •λœ 기본값이 μ‚¬μš©λœλ‹€.

In [8]:
Location = 'births1880.csv'
df = pd.read_csv(Location)

dfλ₯Ό ν™•μΈν•˜λ©΄ 기쑴의 데이터와 λΉ„μŠ·ν•˜κ²Œ 보인닀.

In [9]:
df
Out[9]:
Bob 968
0 Jessica 155
1 Mary 77
2 John 578
3 Mel 973

λ¬Έμ œκ°€ ν•˜λ‚˜ μžˆλ‹€.

read_csv ν•¨μˆ˜κ°€ csv 파일의 첫 번째 쀄을 헀더(header)둜 μ‚¬μš©ν•˜μ˜€λ‹€. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ read_csv ν•¨μˆ˜μ˜ λ§€κ°œλ³€μˆ˜ headerλ₯Ό None으둜 μ„€μ •ν•΄λ³΄μž. νŒŒμ΄μ¬μ—μ„œ None은 null 값을 μ˜λ―Έν•œλ‹€.

In [10]:
df = pd.read_csv(Location, header=None)
df
Out[10]:
0 1
0 Bob 968
1 Jessica 155
2 Mary 77
3 John 578
4 Mel 973

μ—΄ ν•­λͺ©μœΌλ‘œ μ‚¬μš©λ  이름듀을 μ§€μ •ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— 0, 1, 2 λ“±μ˜ 색인을 κΈ°λ³Έκ°’μœΌλ‘œ μ‚¬μš©ν•˜μ˜€λ‹€. λ§Œμ•½ 열에 νŠΉμ •ν•œ 이름듀을 μ‚¬μš©ν•˜κ³  μ‹Άλ‹€λ©΄, namesλΌλŠ” λ§€κ°œλ³€μˆ˜λ₯Ό μ‚¬μš©ν•œλ‹€. μ΄λ•Œ, headerλΌλŠ” λ§€κ°œλ³€μˆ˜λŠ” μƒλž΅κ°€λŠ₯ν•˜λ‹€.

In [11]:
df = pd.read_csv(Location, names=['Names','Births'])
df
Out[11]:
Names Births
0 Bob 968
1 Jessica 155
2 Mary 77
3 John 578
4 Mel 973

ν–‰ 번호 0, 1, 2, 3, 4λŠ” 데이터 ν”„λ ˆμž„ 객체에 기본적으둜 ν¬ν•¨λœ 색인(index) κΈ°λŠ₯으둜 μ‚¬μš©λœλ‹€.

주의: λ™μΌν•œ 색인이 μ—¬λŸ¬ 번 λ‚˜μ˜¬ 수 μžˆλ‹€.

끝으둜 μ§€κΈˆκΉŒμ§€ μ‚¬μš©ν•œ csv νŒŒμΌμ„ μ‚­μ œν•΄ 보자. 더 이상 ν•„μš” μ—†λ‹€.

In [12]:
import os
os.remove('births1880.csv')

데이터 클리닝(cleaning)

λ°μ΄ν„°λŠ” 1880년에 νƒœμ–΄λ‚œ μ•„μ΄μ˜ 이름과 μΆœμƒμˆ˜λ‘œ κ΅¬μ„±λ˜μ–΄ 있으며, 5개의 기둝, 즉 5ν–‰μœΌλ‘œ 이루어져 있고, 결츑치(missing values)λŠ” μ—†λ‹€. 즉, λͺ¨λ“  데이터가 μ™„λ²½ν•˜λ‹€.

그런데 κ²½μš°μ— 따라 μ–΄λ–€ 열에 이질 데이터가 μ‚¬μš©λ˜κ±°λ‚˜ μžˆμ–΄μ•Ό 데이터가 μ—†λŠ” 경우, 즉, κ²°μΈ‘μΉ˜κ°€ μ‘΄μž¬ν•˜λŠ” κ²½μš°κ°€ μžˆλ‹€. 그런 κ²½μš°κ°€ λ°œμƒν•˜λ©΄ 데이터 뢄석이 μ œλŒ€λ‘œ μ§„ν–‰λ˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ μžλ£Œν˜•μ΄ μ„œλ‘œ λ‹€λ₯Έ 데이터가 λ™μΌν•œ 열에 μœ„μΉ˜ν•˜μ§€ μ•ŠλŠ”μ§€, μ•„λ‹ˆλ©΄ κ²°μΈ‘μΉ˜κ°€ μžˆλŠ”μ§€ μ—¬λΆ€λ₯Ό λ¨Όμ € ν™•μΈν•˜μ—¬ λŒ€μ²˜ λ°©μ•ˆμ„ 강ꡬ해야 ν•œλ‹€.

μ–΄λ–€ μ—΄(column)이 λ™μΌν•œ μžλ£Œν˜•μœΌλ‘œ κ΅¬μ„±λ˜μ–΄ μžˆλŠ”μ§€ μ—¬λΆ€λ₯Ό ν™•μΈν•˜λ €λ©΄ 데이터 ν”„λ ˆμž„ 객체의 속성 μ€‘μ—μ„œ dtypesλ₯Ό ν™•μΈν•˜λ©΄ λœλ‹€.

In [13]:
df.dtypes
Out[13]:
Names     object
Births     int64
dtype: object

μœ„ κ²°κ³ΌλŠ” μ•„λž˜ λ‚΄μš©μ„ λ‹΄κ³  μžˆλ‹€.

  • Names ν•­λͺ©μ„ μ‚¬μš©ν•œ 첫째 μ—΄μ˜ μžλ£Œν˜•μ€ object이닀.
    • objectλŠ” νŒŒμ΄μ¬μ—μ„œ μ œκ³΅ν•˜λŠ” μ΅œμƒμœ„ ν΄λž˜μŠ€μ΄λ‹€.
    • 즉, μž„μ˜μ˜ μžλ£Œν˜•μ΄ 첫째 열에 μ‚¬μš©λ˜λ„ λœλ‹€λŠ” μ˜λ―Έμ΄λ‹€.
  • Births ν•­λͺ©μ„ μ‚¬μš©ν•œ λ‘˜μ§Έ μ—΄μ˜ μžλ£Œν˜•μ€ int64이닀.
    • int64λŠ” 64λΉ„νŠΈμš© μ •μˆ˜ μžλ£Œν˜•μ„ λ‚˜νƒ€λ‚Έλ‹€.
    • 즉, μž„μ˜μ˜ μ •μˆ˜λ“€λ§Œ λ‘˜ μ§Έ 열에 μ‚¬μš©λ  수 μžˆλ‹€λŠ” μ˜λ―Έμ΄λ‹€.
    • 예λ₯Ό λ“€μ–΄, 뢀동 μ†Œμˆ˜μ (float), λ¬Έμžμ—΄ λ“± μ •μˆ˜ν˜• μ΄μ™Έμ˜ μžλ£Œν˜•μ„ μ‚¬μš©ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

λͺ¨λ“  열이 μ•„λ‹ˆλΌ, 예λ₯Ό λ“€μ–΄, Births μ—΄μ˜ νƒ€μž…μ„ μ•Œκ³  μ‹Άλ‹€λ©΄, μ•„λž˜μ™€ 같은 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄ λœλ‹€.

In [14]:
df.Births.dtype
Out[14]:
dtype('int64')

데이터 분석

예λ₯Ό λ“€μ–΄, κ°€μž₯ μΈκΈ°μžˆλŠ” 이름 즉, μΆœμƒμˆ˜κ°€ κ°€μž₯ 높은 이름을 μ°ΎκΈ° μœ„ν•΄μ„œ λ‹€μŒ 두 가지 방식 쀑에 ν•œ 가지λ₯Ό ν™œμš©ν•  수 μžˆλ‹€.

  • 방법 1: λ‘˜ μ§Έ 열을 κΈ°μ€€μœΌλ‘œ λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬ν•œ ν›„ 첫째 ν–‰ 선택
  • 방법 2: λ‘˜μ§Έ 열에 λŒ€ν•΄ max() ν•¨μˆ˜ 적용

방법 1: νŠΉμ • 열을 κΈ°μ€€μœΌλ‘œ λ‚΄λ¦Όμ°¨μˆœμœΌλ‘œ μ •λ ¬ν•˜κΈ°

In [22]:
Sorted = df.sort_values(['Births'], ascending=False)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-22-054a15b273d5> in <module>()
----> 1 Sorted = df.sort_values(['Births'], ascending=False)

NameError: name 'df' is not defined

이제 첫째 행을 ν™•μΈν•˜λ©΄ λœλ‹€.

In [16]:
Sorted.head(1)
Out[16]:
Names Births
4 Mel 973

방법 2: νŠΉμ • 열에 λŒ€ν•΄ μΌκ΄„μ μœΌλ‘œ max() λ©”μ†Œλ“œ μ μš©ν•˜κΈ°

In [17]:
df['Births'].max()
Out[17]:
973

데이터 시각화

μ§€κΈˆκΉŒμ§€ 닀룬 λ°μ΄ν„°λŠ” 겨우 5μ€„μ§œλ¦¬μ΄λ‹€. λ”°λΌμ„œ 1880년도에 κ°€μž₯ 인기 μžˆμ—ˆλ˜ 이름이 Melμ΄λΌλŠ” 사싀을 ν•œ λˆˆμ— μ•Œμ•„ λ³Ό 수 μžˆλ‹€. ν•˜μ§€λ§Œ 데이터가 쑰금만 컀져도 그런 정보λ₯Ό μ‰½κ²Œ 눈으둜 확인할 수 μ—†λ‹€. λ”°λΌμ„œ 일반인이 μ›ν•˜λŠ” 정보λ₯Ό μ‰½κ²Œ 얻을 수 μžˆλ„λ‘ ν•˜κΈ° μœ„ν•΄ 데이터λ₯Ό μ‹œκ°ν™”ν•˜μ—¬ μ „λ‹¬ν•˜λŠ” 일이 맀우 μ€‘μš”ν•˜λ‹€.

데이터 ν”„λ ˆμž„ κ°μ²΄λŠ” plot() μ΄λΌλŠ” μ‹œκ°ν™” λ©”μ†Œλ“œλ₯Ό μ œκ³΅ν•œλ‹€.

  • df['Names']: df에 μ €μž₯된 데이터 ν”„λ ˆμž„ 객체의 Names 열을 가리킨닀.
In [23]:
df['Births'].plot()
plt.xlabel("μ‹œκ°„")
plt.show()

λ”°λΌμ„œ Births 열을 μ–»κ³ μž ν•˜λ©΄ μ•„λž˜μ™€ 같이 λͺ…λ Ήν•˜λ©΄ λœλ‹€.

In [19]:
df['Births']
Out[19]:
0    968
1    155
2     77
3    578
4    973
Name: Births, dtype: int64

이제 μ•žμ„œ μ΅œλŒ€ μΆœμƒμˆ˜λ₯Ό ν™•μΈν–ˆλ˜ df['Births'].max()λ₯Ό ν™œμš©ν•˜μ—¬ μ΅œλŒ€ μΆœμƒμˆ˜κ°€ μ‚¬μš©λœ λͺ¨λ“  행을 확인할 수 μžˆλ‹€. λ‹€μŒκ³Ό 같이 ν•˜λ©΄ λœλ‹€.

In [20]:
df['Names'][df['Births'] == df['Births'].max()]
Out[20]:
4    Mel
Name: Names, dtype: object

μœ„ 결과에 μ˜ν•˜λ©΄ 4번 색인 ν–‰, 즉, λ‹€μ„― 번째 μ€„μ—μ„œλ§Œ μ•žμ„œ ν™•μΈν•œ μ΅œλŒ€ μΆœμƒμˆ˜ 973λͺ…이 μ‚¬μš©λ˜μ—ˆλ‹€. 즉, Mel 이름 λ‹¨λ…μœΌλ‘œ κ°€μž₯ 많이 μΆœμƒμ•„μ΄λ“€μ˜ μ΄λ¦„μœΌλ‘œ μ‚¬μš©λ˜μ—ˆλ‹€.

μ•„λž˜μ™€ 같이 λͺ…령해도 λ™μΌν•œ κ²°κ³Όλ₯Ό μ–»λŠ”λ‹€.

  • λ‚΄λ¦Ό 차순으둜 μ •λ ¬ν•œ 후에 μœ„λ‘œλΆ€ν„° 1개의 ν–‰λ§Œ λ³΄μ΄λΌλŠ” λͺ…령이닀.
In [21]:
Sorted['Names'].head(1)
Out[21]:
4    Mel
Name: Names, dtype: object

μ‹œκ°ν™” κ·Έλž˜ν”„μ— μ’€ 더 λ‹€μ–‘ν•œ 정보λ₯Ό μ œκ³΅ν•  수 도 μžˆλ‹€. μ•„λž˜ ν”„λ‘œκ·Έλž¨μ€ κ·Έλž˜ν”„μ— λ‹€μ–‘ν•œ ν…μŠ€νŠΈ 정보λ₯Ό μž…λ ₯ν•˜λŠ” 방법을 λ³΄μ—¬μ£ΌλŠ” μ˜ˆμ œμ΄λ‹€.

In [22]:
# κ·Έλž˜ν”„ λ§Œλ“€κΈ°
df['Births'].plot()

# 데이터셋에 μžˆλŠ” μ΅œλŒ“κ°’
MaxValue = df['Births'].max()

# μ΅œλŒ“κ°’μ„ 가진 이름 확인
MaxName = df['Names'][df['Births'] == df['Births'].max()].values

# κ·Έλž˜ν”„ μœ„μ— 보여쀄 ν…μŠ€νŠΈ
Text = str(MaxValue) + " - " + MaxName

# κ·Έλž˜ν”„μ— ν…μŠ€νŠΈ μΆ”κ°€ν•˜κΈ°
plt.annotate(Text, xy=(1, MaxValue), xytext=(8, 0), 
                 xycoords=('axes fraction', 'data'), textcoords='offset points')

plt.show()