[Python] Pandas 완전정복2 - 데이터 변형, 병합, 정규표현식 조건
Pandas 완전정복2 - 데이터 변형, 병합, 정규표현식 조건
1. Group by를 통한 데이터 변형
특정 칼럼의 값들을 기준으로 데이터를 재정렬하거나 연산하고 싶을 때 group by를 이용합니다.
df.groupby(묶음의 기준이 되는 칼럼명)[연산을 적용할 칼럼].적용받는 연산()
import seaborn as sns
tip = sns.load_dataset('tips')
tip
tip이라는 데이터에는 day라는 범주형 변수가 존재합니다.
요일(day)에 따른 총 지불액의 평균값을 구하고 싶다면
'day를 기준으로 groupby를 진행하고 total_bill 변수에 mean 연산을 적용해주면 됩니다.'
이를 코드로 구현하면 아래와 같습니다.
#요일(day)에 따른 총 지불액의 평균값
#기준 칼럼 - day, 연산 칼럼 - total_bill, 연산 - mean
tip.groupby('day')['total_bill'].mean()
기준 칼럼을 2개 이상 사용하고 싶을 때는 groupby 안에 리스트로 칼럼명을 여러개 명시해주면 됩니다.
#요일, 시간별로 팁, 비용, 인원 수의 평균 구하기
tip.groupby(['day', 'time']).mean()
이렇게 groupby로 나온 결과를 새로운 데이터프레임으로 활용할 수 있습니다.
groupby로 나온 데이터의 경우 그룹으로 사용한 변수가 인덱스로 지정되어 있는데
인덱스가 아닌 칼럼으로 사용하고 싶다면 reset_index 메소드를 사용할 수 있습니다.
#group by 결과를 새로운 데이터프레임으로 활용하고 싶을 때
df2 = tip.groupby(['day', 'time']).mean()
df2.reset_index() #인덱스로 지정되어있던 group by 기준변수를 칼럼으로 가져옴
2. melt를 통한 데이터 변형
ID칼럼과 값으로 사용할 칼럼을 지정하고 ID칼럼을 기준으로 값으로 사용하는 칼럼들의 칼럼명과 해당 값들을
아래로 쭉 나열하는 방식으로 재구조화할 때 melt 메소드를 사용할 수 있습니다.
df.melt(id_vars=id로 지정할 칼럼, value_vars=value로 지정할 칼럼, var_name='var', value_name='value')
tip데이터를 활용해서 day와 time을 ID로 하고, total_bill과 tip을 값으로 가지는 새로운 데이터프레임을 생성하는 법은 다음과 같습니다.
#id는 day와 time, value는 total_bill과 tip으로 하는 데이터프레임
tip.melt(id_vars = ['day', 'time'], value_vars = ['total_bill', 'tip'],
var_name = 'bills/tips')
데이터 시각화시 melt를 이용해 내가 원하는 형태의 자료를 중심으로 데이터를 변형하고 편리하게 사용할 수 있습니다.
3. pivot table을 통한 데이터 변형
melt하거나 변형을 통해 여러 형식으로 뒤섞인 데이터프레임을 구별하기 쉽게 바꾸고 싶을 때 사용하는 메소드입니다.
pivot()은 인덱스와 행, 열을 하나하나 지정해서 데이터를 보기 좋게 구축합니다.
행, 열에 속하는 값에 각각의 value가 하나씩 매칭되어야 작성할 수 있습니다.
df.pivot(index = 'index', columns = 'column', values = 'values')
예를 들어 날짜와 시간에 따른 평균 지불비용을 보여주는 pivot table을 만들고 싶을 때 아래와 같은 코드를 사용합니다.
#날짜와 시간에 따른 평균 지불비용이 담긴 데이터프레임 생성
df = tip.groupby(['day', 'time'])['total_bill'].mean().reset_index()
#피벗 테이블로 변형
df.pivot(index = 'day', columns = 'time', values = 'total_bill')
4. 함수를 적용한 데이터 변형(apply)
특정 조건을 만족하는 새로운 칼럼을 만들거나, 기존 데이터에 반복적인 작업을 통해 데이터를 변형하고 싶을 때
함수를 데이터프레임에 일괄적으로 적용할 수 있습니다.
판다스에서 사용 가능한 반복문의 일종이라고 생각할 수 있으며, 모든 행이나 열에 대해 같은 함수를 반복적으로 적용해줍니다.
df.apply(function, axis = 1 or 0) #function을 행이나 열에 반복적으로 적용
예를 들어 tip데이터의 total_bill을 통해 각 손님들이 얼마만큼의 돈을 냈는지를 범주화하는 '수익'칼럼을 생성하려고 합니다.
총 지불비용이 10이하이면 '조금냄'총 지불비용이 10초과 30이하이면 '보통'총 지불비용이 30이상이면 '많이냄'을 값으로 갖는 '수익'칼럼을 생성합니다.
#적용할 함수 생성
def new_col(x):
if x['total_bill'] <= 10:
return '조금냄'
elif (x['total_bill'] > 10) & (x['total_bill'] <= 30):
return '보통'
elif x['total_bill'] > 30:
return '많이냄'
tip['수익'] = tip.apply(new_col, axis = 1) #axis = 1, 열에 적용
tip
5. 데이터프레임 병합1 - concat
형식이 같은(동일한 칼럼을 가진) 두 데이터를 그대로 위아래로 이어붙이거나,
공통된 ID칼럼을 공유하는 두 데이터를 오른쪽으로 이어 붙일 때 주로 사용하는 메소드입니다.
pd.concat([df1, df2], axis = 0) #두 데이터를 위아래로 이어붙임
pd.concat([df1, df2], axis = 1) #df1의 오른쪽에 df2를 이어붙임
concat은 데이터를 그대로 이어붙이기 때문에 정렬이 다르게 되어있다면
ID가 다른 두 정보를 잘못 연결할 수도 있어서 주의해야 합니다.
#나라 정보 데이터프레임 생성
data = {'Country': ['Belgium', 'France', 'Germany', 'Netherlands', 'United Kingdom'],
'Population': [11.3, 64.3, 81.3, 16.9, 64.9],
'Area': [30510, 671308, 357050, 41526, 244820],
'Capital': ['Brussels', 'Paris', 'Berlin', 'Amsterdam', 'London']}
df = pd.DataFrame(data)
#concat을 사용하기 위해 데이터를 위아래로 쪼갬
df1 = df.loc[:2]
df2 = df.loc[3:]
pd.concat([df1, df2], axis = 0) #axis = 1로 하면 오른쪽에 데이터를 그대로 붙임
6. 데이터프레임 병합2 - merge
merge는 공통된 ID칼럼을 가지고 있는 두 데이터를 연결할 때 사용합니다.
merge는 공통된 ID를 찾아서 연결하는 메소드이기 때문에 정렬이 되어있지 않아도 사용할 수 있습니다.
pd.merge(df1, df2, on = 'id 칼럼', how = '병합방법')
how에 입력할 수 있는 옵션으로는 'inner', 'outer', 'left', 'right'가 있습니다.
how = 'inner' : 공통으로 존재하는 id 값들만 보존하고 나머지는 버리는 방식으로 진행합니다.
how = 'outer' : 모든 id 값을 기준으로 병합, 한쪽에 존재하지 않는 값은 결측으로 남겨집니다.
how = 'left' : 먼저 입력한 데이터(df1)의 id를 기준으로 데이터를 병합합니다.
how = 'right' : 나중에 입력한 데이터(df2)의 id를 기준으로 데이터를 병합합니다.
#merge 사용 예시
df3 = df[['Country', 'Population', 'Area']]
df4 = df[['Country', 'Capital']]
#수도 정보가 누락된 데이터에 수도정보를 다시 불러와서 합칠 때
#id칼럼인 Country가 동일한 행에 수도 데이터를 붙여야 함
pd.merge(df3, df4, on = 'Country', how = 'inner')
7. 정규표현식을 이용한 조건
특정 조건을 만족하는 행, 열을 찾기 위해서 df.filter라는 메소드를 사용할 수 있으며,
정규표현식을 이용해 조건을 달아주는 regex 옵션을 사용합니다.
df.filter(regex = '조건')
1) 칼럼명에서 원하는 문자/문자열을 검색
df.filter(regex = '문자열')
칼럼명이 문자열을 포함하기만 하면(완전히 일치하지 않아도) 해당 칼럼을 출력합니다.
#칼럼명에서 원하는 문자/문자열을 검색
df.filter(regex = 'Co')
2) 칼럼명에서 특정 문자열이 들어가있는 모든 열을 검색
df.filter(regex = '[문자열]')
칼럼명이 문자열을 포함하기만 하면(완전히 일치하지 않아도) 해당 칼럼을 출력합니다.
위 메소드와의 차이점은 입력한 문자열 전체가 아니라 한글자씩 검색한다는 점입니다.
#칼럼명에서 특정 글자가 들어가있는 모든 열을 검색
df.filter(regex = '[CO]') #c 혹은 o가 있는 열 모두 반환
#대소문자를 다르게 인식함
df.filter(regex = '[aA]') #a가 들어가는 칼럼
#c혹은 o가 있는 열
#a가 들어가는 열
특정 문자로 시작하는 칼럼을 찾고싶다면 정규표현식 앞에 ^를 붙여줍니다.
df.filter(regex='^[aA]') # [] 안에 찾고 싶은 값들을 직접 입력
# ^로 시작하는 것들만 찾기
3) 완전히 같은 값이 존재하는 행 검색
값이 문자형으로 되어있는 칼럼에서 특정 문자열과 완전히 같은 값이 존재하는 행을 검색할 수 있습니다.
df[df[column].isin([검색하려는 문자열])
리스트 내에 있는 값들 중 하나라도 완전히 같은 값이 있다면 해당 행을 출력합니다.
df[df['Country'].isin(['France', 'Ger', 'America', 'Belgium'])]
#isin 메소드는 리스트 내 원소 중 완전히 같은 값이 존재할때 해당 행을 반환
4) 특정 문자열로 시작하거나 끝나는 행 검색
특정 문자열로 시작하는 행을 검색할 때는 df[df[column].str.startswith(검색하려는 문자열)]
특정 문자열로 끝나는 행을 검색할 때는 df[df[column].str.endswith(검색하려는 문자열)]
df[df['Capital'].str.startswith('B')] # .str.startswith() - 시작하는 문자열 찾기
df[df['Capital'].str.endswith('s')] # .str.endswith() - 끝내는 문자열 찾기
5) 특정 문자열을 포함하는 행 검색
특정 문자열을 포함하는 행을 검색할 때는 df[df[column].str.contains(검색하려는 문자열)]
여러 문자열에 대해 검색하고 싶을 때는 문자열 | 문자열 | 문자열 ...의 형식으로 입력하면 된다.
df[df['Capital'].str.contains('ss')] # .str.contains() - 가지고있는 문자열 찾기