티스토리 뷰
항상 시작은 CRISP-DM
과제를 수행할 때 기본 프로세스 - 이 방법론의 기초에서 일을 하게 될 가능성이 높다.
비지니스 이해 <-> 데이터 이해 -> 데이터 평가 <-> 모델링 -> 평가 -> 배포
평가 -> 비지니스 이해
비지니스 이해 단계는 문제를 정의하는 단계.
회사에서 무엇을 기대하는 가? 회사의 문제를 해결하는 지를 기대하는 것이다.
데이터 분석, 모델링을 가지고 문제를 해결하는 것
1단계 데이터 분석
기본 구조가 2차원 수치하고 범주
기본 분석 단위 - 행
범주는 그룹을 짓는 것 - 공통된 특징
x : feature 독립변수
y : target, label 종속변수
분석 단위 : 샘플,관측치, 인스턴스(헷갈릴 수 있다), data point
한 행이 시간 단위로 쌓여있어야 한다.
numpy 수치 연산, pandas 비지니스 모델링
loc,groupby는 꼭 알아둬러.
데이터 전처리
데이터 천처리에는 두 가지 단계
1. 분석을 위한 데이터 구조 만들기
2. 모델링을 위한 전처리
SQL을 더 배워야 한다.
목표
1. 분석을 위한 데이터 구조를 이해하고 생성할 수 있다.
2. 데이터 분석 절차를 이해하고 분석 도구를 사용할 수 있다.
데이터프레임 변경
- 열 이름 변경
- 열 추가
- 열 삭제
- map,cut
열 추가와 열 삭제는 반드시 알아야 한다.
열 이름 변경
columns 속성 변경 : 모든 열 이름 변경
tip.columns =[ '컬럼명1','컬럼명2'....]
그런데 너무 길다.
rename() 메소드 사용 : 지정한 열 이름 변경
tip.rename(columns = {컬럼명: 새로 변경할 이름 ,inplace=True} 딕셔너리
inplace가 없으면 수정한 것처럼 조회한다.
inplace를 true로 해야 원본 바뀐다.
열 추가
de[추가할 컬럼명] = de[수치형 컬럼명] / de[수치형 컬럼명2] * 100
없는 열을 변경하면 그 열이 맨 뒤에 열이 추가된다.
titanic['col3'] = titanic['col1']+ titanic['col2']
지정한 위치에 열을 추가하기 위해서는, insert() 메소드를 사용하면 된다.
df.insert(넣을 인덱스 자리, 추가할 컬럼명, 수치연산)
titanic.insert(1, 'col3', titanic['col1']+ titanic['col2'])
열 삭제
drop() 메소드를 사용해 열 삭제
axis=0 행 삭제
axis=1 열 삭제
여기도 inplace
열 두 개 삭제하려면 리스트로 입력받는다.
titanic.drop( ['컬럼1','컬럼2'], axis=1, inplace=True)
만약 작년 급여를 계산하려면, 올해 급여/ (1+ 인상률 /100)
그걸 계산하면 된다.
data['컬럼명'].value_counts()
np.where로 해당 조건 값을 변경하고 추가할 수 있다.
da['Job'].value_counts()
da['Job']=np.where(data['Job']>2,'sat','unsat')
삭제하기 전에는 돌리기 어려우므로, .copy를 이용하여 백업을 만들어 놓는다.
여러 열을 삭제할 떄는 리스트로 묶어준다.
da2.drop('In', axis=1, inplace=True)
da2.drop(['In','Out'],axis=1, inplace=True)
값 변경
값을 변경할 때는 해당 값을 주면 전체 행에 해당 값이 들어간다.
da['In'] = 0
조건에 의한 값을 변경하려면 loc을 사용하면 된다.
da.loc['In'>20, 'In'] =0
IN이 20보다 클때, IN이라는 컬럼에서 0으로 만든다는 뜻이다.
np.where로도 값 변경이 가능하다. 다만, 이때는 인덱스 값이므로 따로 할당해줘야 한다.
da['IN'] = np.where(da['IN']>20,da['IN'],0)
원래 있던 값으로 유지하고 싶을 경우, 위처럼 넣어주면 된다.
map, cut 메소드
map은 파이썬의 map 함수와 유사하다.
각 값을 map의 매개변수를 실행한 값을 넣어준다.
실행함수는 딕셔너리 형태로 넣어준다.
data['G'] = data['G'].map({'M': 1, 'F': 0})
cut은 숫자형 변수를 범주형 변수로 만드는 데 유용하다.
나이를 연령대로, 구매액을 등급으로, 한마디로 구간을 나눠주는 함수.
균등분할할 수도 있고, 구간을 지정해줘서 분할할 수도 있다.
a_group = pd.cut(da2['A'], 3) #균등 분할
a_group2 = pd.cut(da2['A'], 3, labels = ['a','b','c']) #균등 분할 후에 이름을 붙인다
원하는 구간으로 나누려면, bins=[]를 따로 지정해줘야 한다.
a_group2 = pd.cut(da2['A'], bins =[0, 40, 50, 100] , labels = ['y','j','s'])
이것이 최종 형태이다.
당연하지만, bins의 개수 -1이 label의 개수이다.
cut을 하고 a.value_counts()를 했을 때,
() 은 <나 >을 의미하고, []은 <=나 >=를 의미한다.
cut으로 나누면, ](<=) , ( ], ( ], (
이런식으로 나눠진다.
값의 범위 중 오른쪽(큰값)이 아닌 왼쪽(작은값)이 포함되도록 하려면 pd.cut 함수 옵션에 right = False 라고 지정
cut으로 나온 결과는 시리즈로 나오므로, 다시 데이터프레임에 넣거나 추가할 수도 있다.
데이터 프레임의 결합
contcat, merge, pivot
pd.concat : 인덱스(행), 칼럼 이름(열) 기준으로 결합
pd.merge() : 매핑 기준은 특정 키 기준으로 결합.
pd.concat
concat은 붙이는 것이다. axis=0은 위아래로 붙이는 것 칼럼 이름 기준.
axis=1은 옆으로 붙이는 것.
Join 방법
Outer : 모든 행과 열 합치기 (기본값) - 모든 행은 유지하고, 없는 건 NaN -> FULL OUTER JOIN
Inner : 같은 행과 열만 합치기(같은 컬럼 이름이 있는 놈들만 합친다.)
axis=1일 때는 행 인덱스가 기준이 된다.
왼쪽에서 오른쪽으로 붙인다.
컬럼 이름이 같아도 붙을 수 있다. 이름을 좀 변경시켜줘야 헷갈리지 않는다.
pd.concat([dataframe1, dataframe2], axis = 0, join = 'inner')
위아래로 붙였을 떄는 인덱스 리셋을 해야 한다.
s1 = sa1.groupby('Date')['Qty'].agg(qty1 = 'sum')
agg에서 컬럼명을 지정할 때는 컬럼명 = 집계함수 이렇게 하면 된다.
merge
판다스에서 조인은 어떠한 컬럼의 값이 같을 때 다른 값들로 채워넣고 싶을 때 사용한다.
지정한 칼럼의 값을 기준으로 병합한다.
옆으로만 병합한다.
어떤 칼럼을 기준으로 삼을지를 고심해야 한다. 예제는 A를 기준으로 삼았을 떄의 merge
inner : 같은 값만(A를 기준으로 삼으면, A가 같은 행만 출력)
outer : 모두(모든 행을 유지하고, 없는 행은 Nan)
left : 왼쪽 df는 모든 행 유지, 오른쪽 df는 A가 같은 값만 -> Left Outer JOIN
right : left의 반대. Right Outer JOIN
pd.merge(df1,df2, how='방법', on='어떤 컬럼을 기준으로 할지')
pd.merge(df1,df2, how='inner', on='A')
만약 on에 같은 컬럼이 없으면 에러가 난다.
inner는 on만 쓰면 되지만, 나머지는 left_on, right_on으로 써줘야 한다.
left_on은
한번에 여러 개의 데이터프레임을 결합하고 싶을 땐 다음과 같이 사용
from functools import reduce
reduce(lambda x,y: pd.merge(x,y, on='Col1', how='outer'), [df1, df2, df3])
from functools import reduce
s_mer = reduce(lambda x,y: pd.merge(x,y, on='qty', how='inner'), [s1, s2, s5,s11])
집계 후 열 이름 변경하려면, rename이나 columns를 사용한다.
s1 = s1.groupby('Date',as_index=False)['Q'].agg('sum')
s1.columns =['Date','Q1']
as_index=False를 써야 merge의 기준이 되는 date가 나오므로 반드시 써줄 것.
s_mer = reduce(lambda x,y: pd.merge(x,y, on='Date', how='outer'), [s1, s2, s5,s11])
date가 기준이므로 행이 똑같아 옆으로 붙여진다.
만약에 이름을 바꾸지 않고, Qty를 기준으로 한다면 아래로 붙여진다.
left_on,right_on은 칼럼 이름이 다를 때 같다고 지정해주고 싶을 때 쓴다.
만약에 컬럼이 다른 데이터프레임에 각각 있다면?
1. merge를 먼저 하고,
2. 그 다음에 groupby로 묶는다.
all= pd.merge(s1,pro,how='inner',on='Pro_ID') #먼저 merge를 하고
s11 = all.groupby('Date',as_index=False)['Q'].agg('sum') #각각에 대해 합계를 구해본다.
c11 = all.groupby('Cat'as_index=False)['Q'].agg('sum')
all= pd.merge(s1,pro) #아무것도 안 넣으면 자동으로 inner가 된다.
이렇게 데이터 프레임을 묶어서 집계를 볼 수 있다.
pivot
결합은 아니지만 집계 후 데이터프레임을 변형해서 조회하는 데 종종 사용한다.
tmp = pd.merge(s1, pro)
tmp2 = temp.groupby(['Date', 'Cat'], as_index = False)['Q'].sum()
tmp3 = tmp2.pivot(index= 'Cat', columns='Date' ,values='Q')
일별, 카테고리별 판매량을 집계한 후에, pivot으로 만들 수도 있다.
index=행, columns=열, values=값이다.
노하우
데이터 집계를 위해서는 일단 테이블들을 merge를 한 후에 찾는걸 추천한다.
그래야만 groupby로 묶을 수 있기 때문이다.
temp라는 변수로 일단 다 묶어두고, 집계값만 이름을 달리하여 계속해서 재사용한다.
state_qty=temp2.groupby('St',as_index=False)['A'].sum()
state_qty.sort_values(by='A',ascending=False).head(3)
sort_values를 사용하면, 최대 값 추출도 깔끔하게 만들 수 있다.