>>> import pandas as pd
>>> data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
'year': [2000, 2001, 2002, 2001, 2002, 2003],
'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
>>> df = pd.DataFrame(data)
df
>>> df.state == 'Ohio'
>>> import numpy as np
>>> df['East/West'] = np.where(df.state == 'Ohio', 'East', 'West')
df
>>> dic = {'one': 1, 'two': 2, 'three': 3}
>>> s = pd.Series(dic)
s
>>> s.index.name = 'english'
>>> s.index = ['two', 'three', 'four']
s
>>> s['four'] = np.nan
s
>>> df
>>> df['pop'][0] = np.nan
df
>>> df.isnull()
df.isnull().sum()
>>> df['pop']
df[['pop']]
>>> df.query('pop == 1.7')
>>> df.query('pop == NaN')
df.query('pop == np.nan')
#query 로는 NaN값을 찾을 수 없다 -> NaN은 문자도, 숫자도 아니다
>>> np.nan == np.nan
False #NaN은 실제하는 값이 아니기 때문에 비교할 수 없다
>>> pd.Series(['a','b','c','d'], index = ['가', '나', '다'])
ValueError: Length of values (4) does not match length of index (3)
#value의 개수와 index의 개수가 맞지 않다
>>> ser = pd.Series([1.0, np.nan, 3.5, np.nan, 7.0])
>>> ser.mean()
np.round(ser.mean(), 2)
>>> m = np.round(ser.mean(), 2)
ser.fillna(m)
>>> ser1 = pd.Series([1,6,7,8,6,3,2])
ser1
>>> ser1.rank()
>>> ser1.rank(method = 'first')
ser1.rank(method = 'first', ascending = False)
>>> frame = pd.DataFrame(np.random.randn(4,3),columns=list('bde'),
index = ['utah','ohio','texas','oregon'])
frame
>>> df = frame.copy()
df
>>> df.sum(axis = 0)
>>> df.apply(sum)
>>> df.loc['sum'] = df.apply(sum)
df
>>> df.loc[['utah', 'ohio']]
>>> df.iloc[[0,1]]
>>> df[:2]
>>> #df['ohio']
df.loc['ohio']
>>> data = pd.DataFrame({'food' : ['bacon', 'pulled pork', 'bacon',
'Pastrami', 'corned beef', 'Bacon',
'pastrami', 'honey ham', 'nova lox'],
'ounces' : [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
data
#해당 육류가 어떤 동물의 고기인지 알려주는 칼럼을 추가하자
>>> meat_to_animal = {'bacon' : 'pig', 'pulled pork' : 'pig',
'pastrami' : 'cow', 'corned beef' : 'cow',
'honey ham' : 'pig', 'nova lox' : 'salmon'}
#방법1
>>> data['animal'] = data['food'].map(lambda x: meat_to_animal[x.lower()])
#방법2
>>> data['animal'] = data['food'].str.lower().map(meat_to_animal)
>>> data
>>> data = pd.Series([1., -999., 2., -999., -1000., 3.])
data
>>> data.replace(-999, np.nan)
>>> data.replace([-999, -1000], np.nan)
>>> data.replace([-999, -1000], [np.nan, 0])
>>> data.replace({-999 : np.nan, -1000 : 0})
>>> data = pd.DataFrame({'food' : ['bacon', 'pulled pork', 'bacon',
'Pastrami', 'corned beef', 'Bacon',
'pastrami', 'honey ham', 'nova lox'],
'ounces' : [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
data
>>> meat_to_animal = {'bacon' : 'pig', 'pulled pork' : 'pig',
'pastrami' : 'cow', 'corned beef' : 'cow',
'honey ham' : 'pig', 'nova lox' : 'salmon'}
>>> data['animal'] = data['food'].str.lower()
data
>>> data['animal'] = data['animal'].replace(meat_to_animal)
data
map 메서드롤 활용해 새로운 자료구조를 만들지 않고 그 자리에서 바로 축 이름을 변경하는 것이 가능하다
>>> data = pd.DataFrame(np.arange(12).reshape((3, 4)),
index=['Ohio', 'Colorado', 'New York'],
columns=['one', 'two', 'three', 'four'])
data
>>> f = lambda x: x[:4].upper()
f("abcdef")
'ABCD'
>>> data.index
>>> data.index.map(f)
>>> data.index = data.index.map(f)
data
#같은 방법으로 칼럼의 이름도 변경할 수 있다
>>> data.columns.map(f)
>>> data.columns = data.columns.map(f)
data
>>> data = pd.DataFrame(np.arange(12).reshape((3, 4)),
index=['Ohio', 'Colorado', 'New York'],
columns=['one', 'two', 'three', 'four'])
data
>>> data.rename(index = str.title, columns = str.title)
>>> data.rename(index = {'Ohio' : 'India'}, columns = {'Three' : 'Peekaboo'})
'.rename()' 을 사용하면 DataFrame을 직접 복사해서 index와 columns 속성을 갱신할 필요 없이 바로 변경할 수 있다. 원본 데이터를 바로 변경하려면 'inplace = True' 옵션을 넘겨주면 된다
연속성 데이터는 종종 개별로 분할하거나 분석을 위해 그룹별로 나누기도 한다
pandas의 cut 함수를 이용해서 그룹으로 나눌 수 있다
>>> ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
>>> bins = [18, 25, 35, 60, 100]
>>> pd.cut(ages, bins)
>>> cats = pd.cut(ages, bins)
cats #그룹 이름이 담긴 배열
>>> cats.codes #그룹의 번호(?)
>>> cats.categories #카테고리 이름
>>> cats.value_counts() #pd.cut() 결과에 속한 그룹의 수
>>> type(cats)
>>> group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
>>> pd.cut(ages, bins, labels = group_names)
>>> pd.qcut(ages, 4) #4분위로 분류
>>> qc = pd.qcut(ages, 4)
qc.value_counts()
>>> data = pd.DataFrame(np.random.randn(1000, 4))
>>> data.describe()
#절대값 3을 초과하는 값이 들어있는 모든 로우 선택 -> .any()
>>> data[(np.abs(data) > 3).any(1)]
#np.sign(data) : data 값이 양수인지 음수인지에 따라 1이나 -1이 담긴 배열을 반환한다
>>> np.sign(data).head()
>>> data[np.abs(data) > 3] = np.sign(data) * 3
Series나 DataFrame의 '로우' 를 임의 순서로 재배치한다
순서를 바꾸고 싶은 만큼의 길이를 permutation 함수에 입력한다
iloc 기반의 색인이나 take 함수에서 사용 가능하다
>>> np.random.permutation(10)
>>> import pydataset
>>> mpg = pydataset.data("mpg")
mpg
>>> np.random.permutation(len(mpg))
>>> sample_index = np.random.permutation(len(mpg))
mpg.take(sample_index)
#데이터를 30%만 출력해보자
>>> mpg_per = mpg.take(sample_index)
int(len(mpg_per)*0.3)
70
>>> mpg_per[ :70]
#치환 없이 일부만 임의로 선택 -> .sample()
>>> mpg_per.sample(70)
>>> mpg_per.sample(frac = .3)
통계 모델이나 머신러닝 애플리케이션을 위한 데이터 변환
분류값을 '더미' 나 '표시자' 행렬로 전환하는 것
어떤 DataFrame의 한 칼럼에 k가지의 값이 있다면, k개의 칼럼이 있는 DataFrame이나 행렬을 만들고, 값으로는 1과 0을 채워 넣을 것이다 (one-hot-encoding)
>>> df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
'data1': range(6)})
df
>>> df['key']
>>> pd.get_dummies(df['key'])
축에 대해 다중(둘 이상) 색인 단계를 지정할 수 있게 해준다
높은 차원의 데이터를 낮은 차원의 형식으로 다룰 수 있게 해주는 기능이다
.unstack() : 인덱스가 칼럼으로
.stack() : 칼럼이 인덱스로
>>> data = pd.Series(np.random.randn(9),
index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],
[1, 2, 3, 1, 3, 1, 2, 2, 3]])
data
data는 MultiIndex를 색인으로 하는 Series이다
바로 위 단계의 색인을 이용해서 하위 계층을 직접 접근할 수 있으며,
이렇게 계층적으로 색인된 객체는 데이터의 부분집합을 '부분적 색인으로 접근' 하는 것이 가능하다
>>> data.unstack()
>>> data.unstack().stack()
>>> frame = pd.DataFrame(np.arange(12).reshape((4, 3)),
index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
columns=[['Ohio', 'Ohio', 'Colorado'],
['Green', 'Red', 'Green']])
frame
>>> frame.unstack()
>>> frame.stack()
>>> frame.stack().unstack()
.swaplevel() 은 넘겨받은 두 개의 계층 번호나, 이름이 뒤바뀐 새로운 객체를 반환한다
(데이터는 변경되지 않는다)
>>> frame.index.names = ['key1', 'key2']
>>> frame.columns.names = ['state', 'color']
frame
>>> frame.swaplevel('key1', 'key2')
>>> frame.sort_index(level = 1)
>>> frame.swaplevel(0,1).sort_index(level = 0)
>>> frame = pd.DataFrame({'a': range(7), 'b': range(7, 0, -1),
'c': ['one', 'one', 'one', 'two', 'two', 'two', 'two'],
'd': [0, 1, 2, 0, 1, 2, 3]})
frame
#칼럼 a,b,c,d 중 하나를 인덱스로 보내고 싶다면
>>> frame.set_index('c')
>>> frame_c = frame.set_index('c')
frame_c
>>> frame_c.reset_index()
>>> frame = frame_c.reset_index()
frame
>>> frame.set_index(["a", "b"])
>>> frame.set_index(["a", "b"], drop=False)
#'drop=False' : drop 시키지 않겠다는 의미, 이렇게 입력하지 않으면 DataFrame에서 삭제될 수 있다
하나 이상의 키를 사용해서 데이터 집합의 '로우' 를 합친다 (오른쪽으로 합쳐진다)
>>> df1 = pd.DataFrame({'key' : ['b','b','a','c','a','a','b'], 'data1' : range(7)})
df2 = pd.DataFrame({'key' : ['a','b','d'], 'data2' : range(3)})
#df1은 key 칼럼에 여러개의 a, b 로우를 갖고 있고, df2는 유일한 로우를 갖고 있다
>>> df1
>>> df2
>>> pd.merge(df1, df2) #두 데이타의 중복된 칼럼의 이름을 key로 사용한다
>>> pd.merge(df1, df2, on = 'key') #명시적으로 지정해주는 것이 좋다
merge 함수는 기본적으로 '내부 조인(inner join)' 을 수행하여 '교집합(inner)' 결과를 반환한다
'how' 인자로 'left, right, outer' 를 넘겨서 '외부 조인' 을 수행할 수도 있으며, 외부 조인은 '합집합' 인 결과를 반환한다
>>> pd.merge(df1, df2, how = 'inner')
>>> pd.merge(df1, df2, how = 'outer')
#indicator : 'merge' 라는 이름의 칼럼을 추가하여 각 로우의 소스가 어디인지 나타낸다
#left_only, right_only, both
>>> pd.merge(df1, df2, on = 'key', how = 'outer', indicator = True)
>>> pd.merge(df1, df2, on = 'key', how = 'left', indicator = True)
>>> pd.merge(df1, df2, on = 'key', how = 'right', indicator = True)
>>> pd.merge(df1, df2, left_on = 'lkey')
>>> left = pd.DataFrame({'key1': ['foo', 'foo', 'bar'],
'key2': ['one', 'two', 'one'],
'lval': [1, 2, 3]})
right = pd.DataFrame({'key1': ['foo', 'foo', 'bar', 'bar'],
'key2': ['one', 'one', 'one', 'two'],
'rval': [4, 5, 6, 7]})
>>> left
>>> right
>>> pd.merge(left, right)
>>> pd.merge(left, right, on = 'key1')
병합하려는 key가 DataFrame의 색인일 경우가 있다
이런 경우 left_index = True 또는 right_index = True (또는 둘다) 를 지정해서 해당 색인을 병합 key로 사용할 수 있다
>>> left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],
'value': range(6)})
right1 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
>>> left1
>>> right1
>>> pd.merge(left1, right1, left_on = 'key', right_index = True)
>>> left1.set_index('key')
>>> left1 = left1.set_index('key')
>>> right1
>>> pd.merge(left1, right1, left_index = True, right_index = True)
색인으로 병합할 때 DataFrame.join() 메서드를 사용하면 편리하다
join 메서드는 칼럼이 겹치지 않으며 완전히 같거나 유사한 색인 구조를 가진 여러개의 DataFrame 객체를 병합할 때 사용한다
색인 대 색인으로 두 DataFrame을 병합하려면 그냥 간단하게 병합하려는 DataFrame의 리스트를 join 메서드로 넘기면 되지만, 보통 이런 병합은 '.concat()' 메서드를 사용한다
>>> arr = np.arange(12).reshape((3,4))
arr
>>> arr1 = arr.copy()
arr1
>>> np.concatenate([arr, arr1]) #위, 아래로 합쳐진다
>>> np.concatenate([arr, arr1], axis = 1) #옆으로 합쳐진다
>>> df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'],
columns=['one', 'two'])
df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'],
columns=['three', 'four'])
>>> df1
>>> df2
>>> pd.concat([df1, df2])
>>> pd.concat([df1, df2], axis = 1)
#겹치는 축이 없기 때문에 외부 조인으로 '합집합' 결과를 얻었지만,
#join='inner' 를 입력해서 교집합으로도 구할 수 있다
>>> pd.concat([df1, df2], axis = 1, join='inner')
>>> df1
>>> df3 = df1.loc[['c']]
df3
>>> pd.concat([df1,df3])
표 형식의 데이터를 재배치하는 연산
>>> data = pd.DataFrame(np.arange(6).reshape((2, 3)),
index=pd.Index(['Ohio', 'Colorado'], name='state'),
columns=pd.Index(['one', 'two', 'three'],
name='number'))
data
>>> data.stack()
>>> result = data.stack()
result
>>> result1 = result.unstack()
result1
>>> result1.reset_index()
기본적으로 "가장 안쪽에 있는 레벨부터" 끄집어내지만, 레벨 숫자나 이름을 전달해서 끄집어낼 단계를 지정할 수도 있다
>>> result.unstack(0)
stack 메서드는 누락된 데이터를 자동으로 걸러내기 때문에 연산을 쉽게 원상 복구 할 수 있다
DataFrame을 unstack() 할 때 unstack 레벨은 결과에서 가장 낮은 단계가 된다
melting : 여러개의 칼럼을 한개의 칼럼에 밀어 넣는다
넓은 데이터 형식 -> 사람이 보기에 편함
긴 데이터 형식 -> 컴퓨터가 보기에 편함
>>> df = pd.DataFrame({'key': ['foo', 'bar', 'baz'],
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]})
df
>>> df.melt()
>>> df.melt(['A', 'B'])
>>> df.melt(id_vars = ['key'], value_vars = ['A', 'B'])
>>> df.melt(id_vars = ['key'], value_vars = ['A', 'B', 'C'])
>>> df
>>> pd.read_excel('excel_exam.xlsx')
>>> df = pd.read_excel('excel_exam.xlsx')
>>> df.melt(id_vars = 'class', value_vars = ['math', 'english', 'science'])
>>> df.melt(id_vars = 'class', value_vars = ['math', 'english', 'science'],
var_name = '과목', value_name = '점수')