본문 바로가기

Programming

[Python][Library] 2 Pandas - 3 데이터 처리

반응형
#!/usr/bin/env python
# coding: utf-8

# # Pandas III: 데이터 처리

# # 1. 데이터 합치기

# - merge()
# - join()
# - concat()

# ### 1.1 DBMS 스타일로 DataFrame 합치기

# In[ ]:


from pandas import DataFrame, Series
import pandas as pd
import numpy as np


# #### merge() 함수

# In[ ]:


df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
                    'data1': range(7)})
df2 = pd.DataFrame({'key': ['a', 'b', 'd'],
                    'data2': range(3)})


# In[ ]:


df1


# In[ ]:


df2


# In[ ]:


#pd.merge(df1, df2)
pd.merge(df1, df2, on='key')


# In[ ]:


df3 = pd.DataFrame({'lkey': ['b', 'b', 'a', 'c', 'a', 'a', 'b'],
                    'data1': range(7)})
                   
df4 = pd.DataFrame({'rkey': ['a', 'b', 'd'],
                    'data2': range(3)})


# In[ ]:


pd.merge(df3, df4, left_on='lkey', right_on='rkey')


# ####  1) inner join
# ####  2) outer join
# - left outer join
# - right outer join
# - full outer join

# In[ ]:


pd.merge(df1, df2, how='outer')


# In[ ]:


df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
                    'data1': range(6)})

df2 = pd.DataFrame({'key': ['a', 'b', 'a', 'b', 'd'],
                    'data2': range(5)})


# In[ ]:


df1


# In[ ]:


df2


# In[ ]:


pd.merge(df1, df2, on='key', how='left')


# #### <참고> 데카르트 곱 ( Cartesian product )

# In[ ]:


pd.merge(df1, df2, how='inner')


# In[ ]:


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


# In[ ]:


# 여러 key 지정
pd.merge(left, right, on=['key1', 'key2'], how='outer')


# In[ ]:


# 중복되는 컬럼 이름 자동 변경
pd.merge(left, right, on='key1')


# In[ ]:


# 중복되는 컬럼 이름 뒤에 붙일 문자열 지정
pd.merge(left, right, on='key1', suffixes=('_left', '_right'))


# #### merge 함수 인자 목록
# 인자 | 설명
# :---|:---
# left | 머지하려는 DataFrame 중 왼쪽에 위치한 DataFrame
# right | 머지하려는 DataFrame 중 오른쪽에 위치한 DataFrame
# how | 조인 방법. 'inner', 'outer', 'left', 'right' 기본 값은 inner
# on | 조인하려는 로우 이름. 반드시 두 DataFrame 객체 모두에 있는 이름이어야 한다.
# left_on | 조인 키로 사용할 left DataFrame 컬럼
# right_on | 조인 키로 사용할 right DataFrame 컬럼
# left_index | 조인 키로 사용할 left DataFrame의 색인 로우 (다중 색인일 경우의 키)
# right_index | 조인 키로 사용할 right DataFrame의 색인 로우 (다중 색인일 경우의 키)
# suffixes | 중복되는 컬럼의 이름 뒤에 붙인 문자열 지정
#

# ### 1.2 색인으로 머지하기

# In[ ]:


left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],
                      'value': range(6)})

right1 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])


# In[ ]:


left1


# In[ ]:


right1


# In[ ]:


pd.merge(left1, right1, left_on='key', right_index=True)


# In[ ]:


pd.merge(left1, right1, left_on='key', right_index=True, how='outer')


# #### 다중 색인

# In[ ]:


lefth = pd.DataFrame({'key1': ['Ohio', 'Ohio', 'Ohio',
                               'Nevada', 'Nevada'],
                      'key2': [2000, 2001, 2002, 2001, 2002],
                      'data': np.arange(5.)})

righth = pd.DataFrame(np.arange(12).reshape((6, 2)),
                      index=[['Nevada', 'Nevada', 'Ohio', 'Ohio',
                              'Ohio', 'Ohio'],
                             [2001, 2000, 2000, 2000, 2001, 2002]],
                      columns=['event1', 'event2'])


# In[ ]:


lefth


# In[ ]:


righth


# In[ ]:


pd.merge(lefth, righth, left_on=['key1', 'key2'], right_index=True)


# In[ ]:


pd.merge(lefth, righth, left_on=['key1', 'key2'],
         right_index=True, how='outer')


# In[ ]:


left2 = pd.DataFrame([[1., 2.], [3., 4.], [5., 6.]],
                     index=['a', 'c', 'e'],
                     columns=['Ohio', 'Nevada'])
right2 = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [13, 14]],
                      index=['b', 'c', 'd', 'e'],
                      columns=['Missouri', 'Alabama'])


# In[ ]:


left2


# In[ ]:


right2


# In[ ]:


pd.merge(left2, right2, how='outer', left_index=True, right_index=True)


# #### join() 함수: DataFrame 2개 이상 조인 가능

# In[ ]:


left2.join(right2, how='outer')


# In[ ]:


left1.join(right1, on='key')    # Default: how = 'left'


# In[ ]:


another = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [16., 17.]],
                       index=['a', 'c', 'e', 'f'],
                       columns=['New York', 'Oregon'])


# In[ ]:


another


# In[ ]:


left2.join([right2, another])


# In[ ]:


left2.join([right2, another], how='outer', sort=False)


# ### 1.3 축 따라 이어붙이기

# #### concat()

# In[ ]:


arr = np.arange(12).reshape((3, 4))
arr


# In[ ]:


s1 = pd.Series([0, 1],    index=['a', 'b'])
s2 = pd.Series([2, 3, 4], index=['c', 'd', 'e'])
s3 = pd.Series([5, 6],    index=['f', 'g'])


# In[ ]:


pd.concat([s1, s2, s3])


# In[ ]:


pd.concat([s1, s2, s3], axis=1, sort=False)


# In[ ]:


s4 = pd.concat([s1, s3])
s4


# In[ ]:


pd.concat([s1, s4], axis=1, sort=False)


# In[ ]:


# Default: 'outer'
pd.concat([s1, s4], axis=1, join='inner')


# In[ ]:


# 필요한 컬럼 선택
pd.concat([s1, s4], axis=1, join_axes=[['a', 'c', 'b', 'e']])


# #### 인덱스, 컬럼 명 설정 (계층적 색인 생성)

# In[ ]:


result = pd.concat([s1, s2, s3], keys=['one', 'two', 'three'])
result


# In[ ]:


result.unstack()


# In[ ]:


pd.concat([s1, s2, s3], axis=1, keys=['one', 'two', 'three'], sort=False)


# #### DataFrame

# In[ ]:


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


# In[ ]:


df1


# In[ ]:


df2


# In[ ]:


pd.concat([df1, df2], axis=1, keys=['level1', 'level2'], sort=False)


# In[ ]:


pd.concat({'level1': df1, 'level2': df2}, axis=1, sort=False)


# In[ ]:


pd.concat([df1, df2], axis=1, keys =['level1', 'level2'],
          names=['upper', 'lower'], sort=False)


# #### 인덱스 삭제

# In[ ]:


df1 = pd.DataFrame(np.random.randn(3, 4), columns=['a', 'b', 'c', 'd'])
df2 = pd.DataFrame(np.random.randn(2, 3), columns=['b', 'd', 'a'])


# In[ ]:


df1


# In[ ]:


df2


# In[ ]:


pd.concat([df1, df2], ignore_index=True, sort=False)


# ### 1.4 겹치는 데이터 합치기

# #### combine_first()

# In[ ]:


a = pd.Series([np.nan, 2.5, np.nan, 3.5, 4.5, np.nan],
              index=['f', 'e', 'd', 'c', 'b', 'a'])
b = pd.Series(np.arange(len(a), dtype=np.float64),
              index=['f', 'e', 'd', 'c', 'b', 'a'])
b[-1] = np.nan


# In[ ]:


a


# In[ ]:


b


# In[ ]:


np.where(pd.notnull(b), b, a)
#np.where(pd.notnull(a), b, a)


# In[ ]:


b.combine_first(a)
#b[:-2].combine_first(a[2:])


# In[ ]:


df1 = pd.DataFrame({'a': [1., np.nan, 5., np.nan],
                    'b': [np.nan, 2., np.nan, 6.],
                    'c': range(2, 18, 4)})
df2 = pd.DataFrame({'a': [5., 4., np.nan, 3., 7.],
                    'b': [np.nan, 3., 4., 6., 8.]})


# In[ ]:


df1


# In[ ]:


df2


# In[ ]:


df1.combine_first(df2)


# ---

# # 2. 재형성과 피벗

# ### 2.1 계층적 색인으로 재형성하기

# - stack(): 데이터의 컬럼을 로우로 피벗시킨다.
# - unstack(): 로우를 컬럼으로 피벗시킨다.

# In[ ]:


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


# In[ ]:


result = data.stack()
result


# In[ ]:


result.unstack()


# In[ ]:


result.unstack(0)
result.unstack('state')


# #### 누락된 데이터 처리

# In[ ]:


s1 = pd.Series([0, 1, 2, 3], index=['a', 'b', 'c', 'd'])
s2 = pd.Series([4, 5, 6], index=['c', 'd', 'e'])
data2 = pd.concat([s1, s2], keys=['one', 'two'])
data2


# In[ ]:


data2.unstack()


# In[ ]:


data2.unstack().stack()


# In[ ]:


data2.unstack().stack(dropna=False)


# In[ ]:


df = pd.DataFrame({'left': result, 'right': result + 5},
                  columns=pd.Index(['left', 'right'], name='side'))
df


# In[ ]:


df.unstack('state')


# In[ ]:


df.unstack('state').stack('side')


# ### 2.2 데이터 나열 형식 변경

# #### Pivoting “Long” to “Wide” Format

# #### pivot()

# In[ ]:


data = pd.read_csv('data/macrodata.csv')
data.head()


# In[ ]:


periods = pd.PeriodIndex(year=data.year, quarter=data.quarter, name='date')
columns = pd.Index(['realgdp', 'infl', 'unemp'], name='item')
data = data.reindex(columns=columns)
data.index = periods.to_timestamp('D', 'end')


# In[ ]:


ldata = data.stack().reset_index().rename(columns={0: 'value'})
ldata.head()


# In[ ]:


pivoted = ldata.pivot('date', 'item', 'value')
pivoted.head()


# In[ ]:


ldata['value2'] = np.random.randn(len(ldata))
ldata.head()


# In[ ]:


pivoted = ldata.pivot('date', 'item')
pivoted.head()


# In[ ]:


pivoted['value'].head()


# #### <비교>
# - pivot()
# - set_index().unstack()

# In[ ]:


unstacked = ldata.set_index(['date', 'item']).unstack('item')
unstacked.head()


# #### Pivoting “Wide” to “Long” Format

# #### melt()

# In[ ]:


df = pd.DataFrame({'key': ['foo', 'bar', 'baz'],
                   'A': [1, 2, 3],
                   'B': [4, 5, 6],
                   'C': [7, 8, 9]})
df


# In[ ]:


melted = pd.melt(df, ['key'])
melted


# In[ ]:


reshaped = melted.pivot('key', 'variable', 'value')
reshaped


# In[ ]:


reshaped.reset_index()


# In[ ]:


pd.melt(df, id_vars=['key'], value_vars=['A', 'B'])


# In[ ]:


pd.melt(df, value_vars=['A', 'B', 'C'])


# In[ ]:


pd.melt(df, value_vars=['key', 'A', 'B'])


# ---

# # 3. 데이터 변형

# ### 3.1 중복 제거하기

# In[ ]:


data = DataFrame({'k1': ['one'] * 3 + ['two'] * 4,
                  'k2': [1, 1, 2, 3, 3, 4, 4]})
data


# In[ ]:


data.duplicated()


# In[ ]:


data.drop_duplicates()


# In[ ]:


data['v1'] = range(7)
data


# In[ ]:


data.drop_duplicates(['k1'])


# In[ ]:


data.drop_duplicates(['k1', 'k2'], keep='last')


# ### 3.2 함수나 매핑 이용해 데이터 변형하기

# #### map(), apply()

# In[ ]:


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


# In[ ]:


meat_to_animal = {
  'bacon': 'pig',
  'pulled pork': 'pig',
  'pastrami': 'cow',
  'corned beef': 'cow',
  'honey ham': 'pig',
  'nova lox': 'salmon'
}


# In[ ]:


lowercased = data['food'].str.lower()
lowercased


# In[ ]:


data['animal'] = lowercased.map(meat_to_animal)
#data['animal'] = lowercased.apply(meat_to_animal)
data


# In[ ]:


data['food'].map(lambda x: meat_to_animal[x.lower()])
#data['food'].apply(lambda x: meat_to_animal[x.lower()])


# ### 3.3 값 치환하기

# #### replace()

# In[ ]:


data = pd.Series([1., -999., 2., -999., -1000., 3.])
data


# In[ ]:


data.replace(-999, np.nan)


# In[ ]:


data.replace([-999, -1000], np.nan)


# In[ ]:


data.replace([-999, -1000], [np.nan, 0])


# In[ ]:


data.replace({-999: np.nan, -1000: 0})


# ### 3.4 축 색인 이름 바꾸기

# In[ ]:


data = pd.DataFrame(np.arange(12).reshape((3, 4)),
                    index=['Ohio', 'Colorado', 'New York'],
                    columns=['one', 'two', 'three', 'four'])
data


# In[ ]:


transform = lambda x: x[:4].upper()
data.index.map(transform)


# In[ ]:


data.index = data.index.map(transform)
data


# In[ ]:


data.rename(index=str.title, columns=str.upper)


# In[ ]:


data.rename(index={'OHIO': 'INDIANA'},
            columns={'three': 'peekaboo'})


# In[ ]:


data.rename(index={'OHIO': 'INDIANA'}, inplace=True)
data


# ### 3.5 데이터 분류(빈도수 세기)

# - cut()
# - qcut()
# - value_counts()

# In[ ]:


ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]


# In[ ]:


bins = [18, 25, 35, 60, 100]
cats = pd.cut(ages, bins)
cats


# In[ ]:


cats.codes


# In[ ]:


cats.categories


# In[ ]:


# 빈도수 세기
pd.value_counts(cats)


# In[ ]:


# 경계값 포함 여부
pd.cut(ages, [18, 26, 36, 61, 100], right=False)


# In[ ]:


# 그룹 이름 설정
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
pd.cut(ages, bins, labels=group_names)


# In[ ]:


# 4개의 그룹으로 분류: 데이터의 최소값과 최대값을 기준으로 4등분
data = np.random.rand(20)
pd.cut(data, 4, precision=2)


# In[ ]:


data = np.random.randn(1000)


# In[ ]:


# 4개의 그룹으로 분류: 표본 변위치를 기준으로 4등분
cats = pd.qcut(data, 4)  # Cut into quartiles
cats


# In[ ]:


pd.value_counts(cats)


# In[ ]:


# 변위치 지정( 0 ~ 1 )
pd.qcut(data, [0, 0.1, 0.5, 0.9, 1.])


# ### 3.6 이상치(Outliers) 제거

# In[ ]:


data = pd.DataFrame(np.random.randn(1000, 4))
data.describe()


# In[ ]:


col = data[2]
col[np.abs(col) > 3]


# In[ ]:


data[(np.abs(data) > 3).any(1)]
#data[(np.abs(data) > 3).any(axis=1)]


# In[ ]:


data[np.abs(data) > 3] = np.sign(data) * 3
data.describe()


# In[ ]:


np.sign(data).head()


# ### 3.7 치환과 임의 샘플링

# In[ ]:


df = pd.DataFrame(np.arange(5 * 4).reshape((5, 4)))
sampler = np.random.permutation(5)
sampler


# In[ ]:


df


# In[ ]:


df.take(sampler)


# In[ ]:


df.sample(n=3)


# In[ ]:


choices = pd.Series([5, 7, -1, 6, 4])
choices


# In[ ]:


draws = choices.sample(n=10, replace=True)
draws


# ### 3.8 더미 변수 ( One-Hot-Encoding )

# In[ ]:


df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
                   'data1': range(6)})
df


# In[ ]:


pd.get_dummies(df['key'])


# In[ ]:


dummies = pd.get_dummies(df['key'], prefix='key')
df_with_dummy = df[['data1']].join(dummies)
df_with_dummy


# In[ ]:


np.random.seed(12345)
values = np.random.rand(10)
values
bins = [0, 0.2, 0.4, 0.6, 0.8, 1]
pd.get_dummies(pd.cut(values, bins))


# ---

# # 4. 문자열 다루기

# ### 4.1 문자열 객체 메서드

# In[ ]:


val = 'a,b,  guido'
val.split(',')


# In[ ]:


pieces = [x.strip() for x in val.split(',')]
pieces


# In[ ]:


first, second, third = pieces
first + '::' + second + '::' + third


# In[ ]:


'::'.join(pieces)


# In[ ]:


'guido' in val


# In[ ]:


val.index(',')


# In[ ]:


# 문자열 찾지 못하면 -1 반환
val.find(':')


# In[ ]:


# 문자열 찾지 못하면 예외 발생
val.index(':')


# In[ ]:


val.count(',')


# In[ ]:


val.replace(',', '::')


# In[ ]:


val.replace(',', '')


# ### 4.2 정규표현식

# In[ ]:


import re


# In[ ]:


text = "foo    bar\t baz  \tqux"
re.split('\s+', text)


# In[ ]:


regex = re.compile('\s+')
regex.split(text)


# In[ ]:


regex.findall(text)


# In[ ]:


text = """Dave dave@google.com
Steve steve@gmail.com
Rob rob@gmail.com
Ryan ryan@yahoo.com
"""
pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'

# re.IGNORECASE : 대,소문자 무시
regex = re.compile(pattern, flags=re.IGNORECASE)


# In[ ]:


# findall(): 매칭되는 모든 문자열을 찾아준다.
regex.findall(text)


# In[ ]:


# search(): 첫 번째 매칭되는 문자열(위치)만 찾아준다.

m = regex.search(text)
m
text[m.start():m.end()]


# In[ ]:


# match(): 문자열의 시작부분에서 일치하는 것만 찾아준다.
print(regex.match(text))


# In[ ]:


# sub(): 찾은 패턴을 주어진 문자열로 치환
print(regex.sub('REDACTED', text))


# In[ ]:


# 각 패턴을 그룹으로 설정
pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
regex = re.compile(pattern, flags=re.IGNORECASE)


# In[ ]:


m = regex.match('wesm@bright.net')
m.groups()


# In[ ]:


# findall(): 그룹이 존재하면 튜플로 반환
regex.findall(text)


# In[ ]:


# sub(): 각 패턴의 그룹에 접근( 기호: \1, \2 )
print(regex.sub(r'Username: \1, Domain: \2, Suffix: \3', text))


# ### 4.3 pandas의 벡터화된 문자열

# #### Series의 각 요소에 순차적으로 적용

# In[ ]:


data = {'1': 'a,b,c,d', '2': 'a b c d',
         '3': '  a_b_c_d  '}
sr = pd.Series(data)
sr


# In[ ]:


# 문자열을 담고 있는지 검사
sr.str.contains('a')


# In[ ]:


sr.str[:5]


# In[ ]:


sr.str.split(',')


# In[ ]:


sr.str.strip()


# In[ ]:


sr.str.replace('a', 'kk')


# In[ ]:


sr.str.len()


# In[ ]:


#sr.str.lower()
sr.str.upper()


# In[ ]:


sr.str.join('=')


# #### pandas 문자열의 정규표현식

# In[ ]:


data1 = {'Dave': 'dave@google.com', 'Steve': 'steve@gmail.com',
        'Rob': 'rob@gmail.com', 'Wes': np.nan}
sr1 = pd.Series(data1)
sr1


# In[ ]:


pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'


# In[ ]:


sr1.str.findall(pattern, flags=re.IGNORECASE)


# ---

# In[ ]:


# end of file


# In[ ]:





반응형
LIST