220928 Day24

유예지·2022년 9월 28일

[0927 복습]

1. 데이터 프레임에 새로운 칼럼 추가

>>> 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

2.

>>> 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은 실제하는 값이 아니기 때문에 비교할 수 없다

3.

>>> pd.Series(['a','b','c','d'], index = ['가', '나', '다'])
ValueError: Length of values (4) does not match length of index (3)
#value의 개수와 index의 개수가 맞지 않다

4. 시리즈의 평균값

>>> 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)

5.

>>> ser1 = pd.Series([1,6,7,8,6,3,2])
	ser1

>>> ser1.rank()
>>> ser1.rank(method = 'first')
	ser1.rank(method = 'first', ascending = False)

6. 행 추가하기

>>> 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']

6. 데이터 정제 및 준비

(2) 데이터 변형

② 함수나 매핑을 이용해서 데이터 변형하기

>>> 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

③ 값 치환하기 .replace()

>>> 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
  • 원래 객체를 변경하지 않고 새로운 객체를 생성하려면 '.rename()' 을 사용한다
    '.rename()'은 사전 형식의 객체를 이용해서 축 이름 중 일부만 변경하는 것도 가능하다
>>> 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' 옵션을 넘겨주면 된다

⑤ 개별화와 양자화 (Discretization and Binning)

연속성 데이터는 종종 개별로 분할하거나 분석을 위해 그룹별로 나누기도 한다
pandas의 cut 함수를 이용해서 그룹으로 나눌 수 있다

  • pd.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()
    표준 변위치를 기반으로 데이터를 적당히 같은 크기의 그룹으로 나눌 수 있다
    cut 함수는 데이터의 분산에 따라 각각의 그룹마다 데이터 수가 다르게 나뉘는 경우가 많다
>>> pd.qcut(ages, 4)    #4분위로 분류

>>> qc = pd.qcut(ages, 4)
	qc.value_counts()

⑥ 특잇값(outlier) 찾고 제외하기

>>> 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

⑦ 치환과 임의 샘플링 np.random.permutation()

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)

⑧ 표시자/더미 변수 계산 .get_dummies()

통계 모델이나 머신러닝 애플리케이션을 위한 데이터 변환
분류값을 '더미' 나 '표시자' 행렬로 전환하는 것
어떤 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'])

7. 데이터 준비하기 : 조인, 병합, 변형

(1) 계층적 색인

축에 대해 다중(둘 이상) 색인 단계를 지정할 수 있게 해준다
높은 차원의 데이터를 낮은 차원의 형식으로 다룰 수 있게 해주는 기능이다

① .unstack(), .stack() 메서드

.unstack() : 인덱스가 칼럼으로
.stack() : 칼럼이 인덱스로

  • Series
>>> 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()
  • DataFrame 에서는 두 축(로우, 칼럼) 모두 계층적 색인을 가질 수 있다
>>> 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()

.swaplevel() 은 넘겨받은 두 개의 계층 번호나, 이름이 뒤바뀐 새로운 객체를 반환한다
(데이터는 변경되지 않는다)

>>> frame.index.names = ['key1', 'key2']
>>> frame.columns.names = ['state', 'color']
	frame
    
>>> frame.swaplevel('key1', 'key2')    
  • sort_index() 메서드는 단일 계층에 속한 데이터를 정렬한다 (결과가 사전적으로 정렬되도록 만들어준다)
>>> frame.sort_index(level = 1)
>>> frame.swaplevel(0,1).sort_index(level = 0)

③ DataFrame의 칼럼 사용하기

>>> 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
  • set_index() : 하나 이상의 칼럼을 색인으로 하는 새로운 DataFrame을 생성한다
  • reset_index() : set_index() 와 반대 개념, 계층적 색인 단계가 칼럼으로 이동
#칼럼 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에서 삭제될 수 있다
  • index 관련 메서드
    reindex() / set_index() / reset_index() / sort_index() ...

(2) 두개의 데이터 합치기

① merge

하나 이상의 키를 사용해서 데이터 집합의 '로우' 를 합친다 (오른쪽으로 합쳐진다)

>>> 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에는 2개의 'foo' 로우가, right에도 2개의 'foo' 로우가 있으며 결과적으로는 4개의 'foo' 로우가 된다
>>> 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)

③ 축 따라 이어붙이기 concat

색인으로 병합할 때 DataFrame.join() 메서드를 사용하면 편리하다
join 메서드는 칼럼이 겹치지 않으며 완전히 같거나 유사한 색인 구조를 가진 여러개의 DataFrame 객체를 병합할 때 사용한다

색인 대 색인으로 두 DataFrame을 병합하려면 그냥 간단하게 병합하려는 DataFrame의 리스트를 join 메서드로 넘기면 되지만, 보통 이런 병합은 '.concat()' 메서드를 사용한다

  • Numpy : Numpy는 ndarray를 이어붙이는 concatenate 함수를 제공한다
>>> arr = np.arange(12).reshape((3,4))
	arr
    
>>> arr1 = arr.copy()
	arr1   
    
>>> np.concatenate([arr, arr1])    #위, 아래로 합쳐진다 
>>> np.concatenate([arr, arr1], axis = 1)    #옆으로 합쳐진다
  • pandas : pandas의 concat 함수는 axis = 0 을 기본값으로 하여 새로운 Series 객체를 생성한다
>>> 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])    
  • 로우 색인이 분석에 필요한 데이터를 포함하고 있지 않은 경우 'ignore_index = True' 옵션을 추가해서 써준다

(3) 재형성과 피벗 연산

표 형식의 데이터를 재배치하는 연산

  • stack : 데이터의 칼럼을 로우로 피벗(또는 회전) 시킨다
  • unstack : 로우를 칼럼으로 피벗시킨다
>>> 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 레벨은 결과에서 가장 낮은 단계가 된다

* 넓은(wide) 형식에서 긴 형식(long)으로 melt

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 = '점수')

0개의 댓글