주의: 위 주석은 독자용이 아님.
앞서 살펴 보았듯이 pandas 모듈은 확률과 통계에 최적화된 파이썬 모듈이다. 특히, 데이터프레임(DataFrame) 자료형 클래스는 데이터 분석을 위한 다양한 기능을 제공한다. 데이터프레임 자료형의 기본 특성은 다음과 같다.
pandas의 기초적인 활용에 대해서는 아래 두 사이트를 언급하는 것으로 하고 넘어간다. 강의 시간에 일부 내용을 함께 확인할 예정이다.
먼저 아래 사이트의 내용 중 5.2절까지의 내용을 먼저 본다.
그 후에 아래 사이트 내용을 한 번 훑어 본다.
위 사이트의 소스코드는 아래 사이트를 참조하면 쉽게 얻을 수 있다.
https://github.com/liganega/10-minutes-to-pandas/blob/master/notebooks/10-minutes-to-pandas.ipynb
이제 다시 아내 사이트의 내용 중 5.2절 이후를 살펴본다.
강의노트로 돌아와서 GongSu21 장 내용을 다시 한 번 살펴본다.
In [1]:
from pandas import Series, DataFrame
import pandas as pd
import numpy as np
pd는 pandas를 지칭하며 Series와 DataFrame은 원래 pandas 모듈에서 정의된 함수들이어서 기본적으로
pd.Series() 또는 pd.DataFrame() 형식으로 호출해야 한다.
하지만 많이 사용되는 함수들이기에 두 함수를 따로 임포트 하면 "pd."
부분은 생략이 가능하다.
즉, 로컬 네임스페이스로 import하는 것이 편해서 이렇게 사용한다.
pandas에 대해서 알아보려면 Series와 DataFrame, 이 두 가지 자료 구조에 익숙해져야 한다.
In [4]:
s1 = Series([4, -7, -5, 3])
s1
Out[4]:
index를 지정하지 않으면 어레이 인덱싱에서 사용되는 숫자가 자동으로 사용된다.
In [5]:
s1.values
Out[5]:
In [6]:
s1.index
Out[6]:
In [3]:
s2 = Series([4, -7, -5, 3], index=['a', 'b', 'c', 'd'])
s2
Out[3]:
index를 확인하면 기본 인덱스와 다른 자료형이 사용되었음을 확인할 수 있다.
In [6]:
s2.index
Out[6]:
색인은 대입을 통해서도 변경할 수 있다.
In [7]:
s2.index = ['A', 'B', 'C', 'D']
s2
Out[7]:
In [8]:
s2['C']
Out[8]:
여러 개의 색인을 활용하여 인덱싱을 하면 시리즈 값이 리턴된다.
In [8]:
s3 = s2[['D', 'A', 'B']]
s3
Out[8]:
In [10]:
mask = s2 > 0
mask
Out[10]:
In [11]:
s2[mask]
Out[11]:
In [12]:
s2 * 2
Out[12]:
In [13]:
def f(x):
return x/2 + 1/2
In [14]:
f(s2)
Out[14]:
In [15]:
'B' in s2
Out[15]:
In [16]:
'one' in s2
Out[16]:
시리즈 자료형은 사전 자료형과 매우 비슷하다. 다만 values에 동일한 자료형이 사용되어야 한다는 점에 다르다. 따라서 사전 자료형을 이용하여 시리즈를 쉽게 생성할 수 있다.
In [17]:
dic1 = {'Oh':2300, 'Ts': 1700, 'Or':1600, 'Ah':4500}
s4 = Series(dic1)
s4
Out[17]:
새로운 index를 사용할 경우, 기존의 사전에 사용되지 않은 key에는 값이 누락되었다는 의미로 NaN이 사용된다.
주의: NaN은 Not a Number의 줄임말로 어떤 값도 할당되지 않았음, 즉 널(Null)임을 의미한다.
In [18]:
keys1 = ['Ca', 'Oh', 'Or', 'Ts', 'Gg']
s5 = Series(dic1, index=keys1)
s5
Out[18]:
In [19]:
pd.isnull(s5)
Out[19]:
In [20]:
pd.notnull(s5)
Out[20]:
In [21]:
s4
Out[21]:
In [22]:
s5
Out[22]:
In [23]:
s4 + s5
Out[23]:
In [24]:
s5.name = 'Population'
index의 자료형이 Index 이며, Index 클래스에 name 속성을 변경해주어야 한다.
In [26]:
s5.index
Out[26]:
In [27]:
s5.index.name = 'State'
이제 s5의 name 속성과 s5.index의 속성이 설정되었음을 아래와 같이 확인할 수 있다.
In [28]:
s5
Out[28]:
In [30]:
weed_pd = pd.read_csv("data/Weed_Price.csv", parse_dates=[-1])
weed_pd.head()
Out[30]:
weed_pd에 할당된 데이터프레임에는 총 8개의 Series가 사용되었다. 각각의 시리즈의 이름(name)은 다음과 같다.
State, HighQ, HighQN, MedQ, MedQN, LowQ, LowQN, date
또한 언급된 8개의 시리즈의 index는 모두 기본 index를 사용하고 있다.
In [31]:
data = {'state' : ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],\
'year' : [2000, 2001, 2002, 2001, 2002],\
'pop' : [1.5, 1.7, 3.6, 2.4, 2.9]}
In [29]:
df = DataFrame(data)
df
Out[29]:
사전 자료형을 이용하였기 때문에 시리즈의 순서가 임의로 지정되었다. 특정 순서로 시리즈를 나열하려면 columns 키워드 인자를 이용해야 한다.
In [30]:
DataFrame(data, columns=['year', 'state', 'pop'])
Out[30]:
Series의 경우처럼 index를 지정할 수 있다.
In [34]:
df2 = DataFrame(data, index=['one','two','three','four','five'])
df2
Out[34]:
In [35]:
df3 = DataFrame(df2)
df3
Out[35]:
아래 코드는 기존의 데이터프레임에 컬럼을 확장하는 방식으로 새로운 데이터프레임을 생성한다.
주의: 새 컬럼에 값을 지정하지 않으므로 널값이 할당된다.
In [36]:
df4 = DataFrame(df3, columns=['year', 'state', 'pop', 'debt'])
df4
Out[36]:
컬럼의 이름의 목록은 columns 속성에 저장되어 있다.
In [37]:
df4.columns
Out[37]:
In [38]:
df4['year']
Out[38]:
각각의 컬럼이 Series 자료형임을 확인할 수 있다.
In [39]:
type(df4['year'])
Out[39]:
In [41]:
df4.year
Out[41]:
In [43]:
df4['debt'] = 16.5
df4
Out[43]:
아래 코드는 index의 길이와 동일한 크기의 어레이나 리스트를 활용하는 방법이다.
In [44]:
df4['debt'] = np.arange(5.)
df4
Out[44]:
주의: 정수 5 대신에 부동소수점 5.를 사용하는 이유는 debt 컬럼의 자료형을 float로 설정하기 위함이다.
In [45]:
df4.dtypes
Out[45]:
특정 컬럼의 데이터를 Series를 이용하여 지정할 때는 DataFrame의 색인에 따라 값이 대입되며 없는 색인에는 값이 대입되지 않는다.
In [46]:
val = Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
val
Out[46]:
In [47]:
df4['debt'] = val
df4
Out[47]:
In [48]:
df4.loc['three']
Out[48]:
loc의 리턴값은 시리즈이다.
In [49]:
type(df4.loc['three'])
Out[49]:
컬럼의 이름이 index로 사용되었음에 주의한다.
In [50]:
df4.loc['three'].index
Out[50]:
In [51]:
df4.loc['three'] = [2017, 'GG', 2.3, 3.0]
df4
Out[51]:
In [47]:
df4['eastern']= (df4.state == 'Ohio')
df4
Out[47]:
참고: state == 'ohio'
는 시리즈를 생성한다.
In [48]:
df4.state == 'Ohio'
Out[48]:
In [49]:
del df4['eastern']
df4
Out[49]:
DataFrame의 색인을 이용해서 생성된 칼럼은 내부 데이터에 대한 뷰(view)이며 복사가 이루어지지 않는다. 따라서 이렇게 얻은 Series 객체에 대한 변경은 실제 DataFrame에 반영된다. 복사본이 필요할 때는 Series의 copy 메서드를 이용하자.
In [50]:
df4
Out[50]:
In [51]:
debt_col = df4.debt
debt_col
Out[51]:
아래와 같이 인덱싱을 사용하여 값을 변경할 수는 있지만 경고문이 뜬다. 경고문은 슬라이싱(인덱싱) 결과에 수정을 가할 때 조심해야 한다는 내용이다.
In [52]:
debt_col.loc['one'] = 1.2
하지만 값이 기존의 df4까지 영향을 주는 것을 아래와 같이 확인할 수 있다. 위 경고문의 내용처럼 뷰 방식으로 작동하는 경우 데이터를 수정할 때 매우 조심해야 한다.
In [53]:
df4
Out[53]:
copy()
메소드를 사용하면 앞서 설명한 문제는 발생하지 않는다.
In [54]:
debt_col_copy = df4.debt.copy()
debt_col_copy
의 데이터를 수정하자.
더 이상 경고문이 뜨지 않는다.
In [55]:
debt_col_copy.loc['one'] = -1.2
또한 기존의 df4
가 변경되지 않았음을 확인할 수 있다.
In [56]:
df4
Out[56]:
In [2]:
pop = {'Nevada' : {2001: 2.4, 2002: 2.9},
'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
바깥에 있는 사전의 키 값이 칼럼이 되고 안에 있는 키는 인덱스가 된다.
In [3]:
df5 = DataFrame(pop)
df5
Out[3]:
In [4]:
DataFrame(pop, index=[2001, 2002, 2003])
Out[4]:
In [5]:
df5['Ohio'][:-1]
Out[5]:
In [6]:
df5['Nevada'][:2]
Out[6]:
In [7]:
pdata = {'ohio' : df5['Ohio'][:-1],
'Nevada': df5['Nevada'][:2]}
DataFrame(pdata)
Out[7]:
In [8]:
df5T = df5.T.copy()
df5T
Out[8]:
In [9]:
df5['Nevada'].iloc[0] = 1.0
df5
Out[9]:
In [10]:
df5T
Out[10]:
In [11]:
df5
Out[11]:
In [12]:
df5.index.name = 'year'
df5.columns.name = 'state'
df5
Out[12]:
In [67]:
df5.values
Out[67]:
DataFrame의 칼럼에 서로 다른 dtype이 있다면 모든 칼럼을 수용하기 위해 object라는 dtype이 선택된다. object를 만능 자료형이라 생각하면 편하다. 실제로는 4개의 포인터로 구성된다.
In [68]:
df3.values
Out[68]: