[AI] KT AIVLE(KT 에이블스쿨) 3기 AI 개발자 트랙 파이썬 라이브러리, 데이터 처리, 데이터 분석 -2주차-
주말이 순식간에 지나가고 벌써 월요일이 되었다.. 직장인들이 왜 주말만을 학수고대하는지 간접체험할 수 있었다. 심화적인 내용을 배우기 시작하면 다르겠지만 지금은 아직까진 비교적 여유롭다. 다른 에이블러분들 중 전공자이신 분들도 여유로워하시는 것 같았다. 이번 2주차는 한기영 강사분께서 강의를 해주신다. 선배 기수분들이 '갓'기영이라고 하던데 수업을 들어보니 왜 '갓'이라고 하는지 알 것 같았다.
다다음주부터는 미니프로젝트가 있다고 하는데 얼른 공모전이나 스터디를 구해서 진행해볼까 한다.
파이썬 라이브러리
갓기영 강사님의 강의 덕분에 헷갈렸던 numpy, pandas 라이브러리를 기초부터 다시 정리해볼 수 있어서 의미 있는 강의였다. 오전에 numpy, 오후에 pandas 이론을 배웠고 이론 후에는 간단한 실습으로 배운 이론 내용을 직접 적용해보고 익힐 수 있는 시간을 가졌다.
- 데이터구조
: 분석을 위한 데이터
데이터 구조: 변수(열), 분석단위(행)
- CRISP-DM (Cross-Industry Standard Process for Data Mining)
: business 이해 -> 데이터 이해 -> 전처리 -> 모델링 -> 평가 -> 배포
- business 이해: 무엇이 문제인가? (문제 정의)
데이터 이해: 데이터 어디에 있는지, 진짜 데이터인지. 데이터분석, 데이터 수집 웹크롤링
전처리: 모델링을 위한 데이터 구조 준비
모델링: 검증(예측, 평가) 머신러닝, 딥러닝, 언어지능, 시각지능
평가: 문제가 해결되는가? AI 모델 해석
배포: 웹 서비스 구축
- 분석할 수 있는 데이터
1. 범주형 (-> 1월이 3월의 3배? 즉 계산이 가능하지 않으면 범주형)
: 질적 데이터(정성적 데이터)
- 명목형 데이터: 성별, 시도, 흡연여부 등
- 순서형 데이터: 연령대, 매출등급 등
2. 수치형
: 양적 데이터(정량적 데이터)
- 이산형 데이터: 판매량, 매출액, 나이 등 (셀 수 있는 데이터)
- 연속형 데이터: 온도
- 2차원 데이터
: table, 2차원 array, Data Frame
1. 열
: 결과 - target, y, label, (종속변수)
요인 - features, X, input, (독립변수)
2. 행
: 분석단위, 샘플, 관측치, 데이터 건수
- 리스트
: 값의 집합/ 다른 타입 데이터도 저장 가능/ 요소 변경, 추가, 제거 용이
- Numpy
: array(배열) 만들고, 조회하기 / 배열 연산 및 집계
- Pandas
: Series와 DataFrame / DataFrame 불러오기 및 조건 조회하기
- Numpy
- axis: 배열의 각 축 (0->열 / 1->행)
- rank: 축(axis)의 개수
- shape: 축의 길이, 배열의 크기 ex) (3,2)
a = np.array([1,2,3,4,5])
print(a) # [1,2,3,4,5]
print(type(a)) # <class ‘numpy.ndarray’>
print(a.shape) # (5, ) -> 모양
print(a.ndim) # 1 -> 차원
print(a.dtype) # int32 -> 데이터 형식
print(a[0], a[1]) # 1 2
- 데이터 분석 및 모델링에서 axis 0의 의미
: 분석 단위를 구성
- reshape
: shape을 재설정 가능
reshape(1,-1) -> 1행으로 reshape하는데 열은 자동으로 맞춰줌
-> -1을 쓸 때는 행x열의 약수일 때 만 가능함
- 함수와 메서드
np.mean() -> numpy에 내장된 함수(np.array로 값을 변경 후 값 계산)
리스트.mean() / 배열.mean() -> 메서드
- np.where
: np.where(조건문, 참일 때 값, 거짓일 때 값)
- np.argmax / np.argmin
np.argmax(a, axis=0) : 행 방향 값끼리 비교해 최댓값의 인덱스 반환
np.argmax(a, axis=1) : 열 방향 값끼리 비교해 최댓값의 인덱스 반환
- DataFrame
: 관계형 데이터베이스의 테이블 또는 엑셀 시트와 같은 형태
- Series
: 하나의 정보에 대한 데이터들의 집합
데이터프레임에서 하나의 열을 떼어낸 것(1차원)
- 데이터프레임 정보 확인
df.head(n): 앞쪽 데이터 n개 확인
df.tail(n): 뒤쪽 데이터 n개 확인
df.shape: 데이터프레임 모양확인 (행,열) 형태
df.colums: 열 이름 확인
df.colums.values: np array 형태의 열 이름 확인
list(df): 열 이름이 리스트로 반환
df.colums(): 열 정보 확인
df.dtypes(): 열 데이터 타입 확인
df.info(): 데이터 건수(null개수), 데이터 타입 확인
df.describe(): 개수, 평균, max, min, 사분위 값, 표준편차 등
dataframe 정렬
df.sort_values(by=’컬럼명‘, ascending = False) -> 내림차순
df.sort_values(by=[컬럼명1, 컬럼명2], ascending = [False, True])
df.reset_index(drop = True) -> 정렬 후 인덱스 초기화
- 기본 집계
: 고유값, 합, 평균, 최댓값, 최소값 등 확인
df[‘컬럼명’].unique(): 고유값
df[‘컬럼명’].value_counts(): 열 고유값 개수 확인
df[‘컬럼명’].sum()
df[‘컬럼명’].max()
df[‘컬럼명’].mean()
df[‘컬럼명’].median(): 중앙값
- loc
: df.loc[조건문]
ex) df.loc[df[‘asdf’] > 10]
- isin()
: df.isin([값1,값2,...,값n]): 값1,값2,값n인 데이터만 조회
- between(값1,값2)
: 값1~값2까지 범위안의 데이터만 조회
df.loc[df[‘컬럼명’].between(25,30)]
데이터 처리(1)
- 모델링 가능한 데이터셋
: 모든 셀은 값이 있어야함
모든 값은 숫자
필요시, 숫자의 범위 맞춰야함
- 데이터 분석 연습
: 요인을 정할 때 적합한지 확인해야함 -> 적합하지 않으면 어떻게 변경해야 하는지 생각
- 열 이름 변경
1. tip.columns = [‘바꿀 이름1’,‘바꿀 이름2’, ‘바꿀 이름3’]
-> 모든 컬럼 다 입력해줘야 한다.
2. tip.rename(columns={‘바꾸고 싶은 이름’:‘바꾸려는 이름’}, inplace = True)
inplace = True -> 원본 데이터셋을 바꿈(False면 바꾼 이름으로 조회만 함)
- 열 추가
: insert()메소드를 사용하면 원하는위치에 열을 추가할 수 있음
df.insert(원하는 위치(인덱스), 값)
ex) tip.insert(1, ‘div_tb’, tip[-]/tip[-])
- 열 삭제
: axis = 0 행 삭제 / axis = 1 열 삭제
ex) tip.drop([‘final_amt’, ‘day’]), axis = 1, inplace = True)
- 값 변경
1. 열 전체 값 변경
# tip[‘tip’]의 모든 값을 0으로 바꿈
tip[‘tip’] = 0
2. 조건에 의한 값 변경1
# tip[‘tip’]의 값이 10보다 작을 경우, 0 으로 바꿈
tip.loc[tip[‘tip’] < 10, ‘tip’] = 0
3. 조건에 의한 값 변경2
# tip[‘tip’] 의 값이 10보다 작을 경우 0, 아니면 1로 바꾸기
tip[‘tip’] = np.where(tip[‘tip’] < 10, 0, 1)
- map()
: 범주형 값을 다른 값으로 변경할 때 사용
ex) tip[‘sex’] = tip[‘sex’].map({‘Male’ : 1, ‘Female’ : 0})
- cut()
: 숫자형 변수를 범주형 변수로 변환할 때 사용
# 크기로 3등분해서 등급 구하기
tip[‘tip_grp’] = pd.cut(tip[‘tip’], 3, lavels = [‘c’,‘d’,‘e’] )
# bin = []으로 구간 직접 나누기
# labels = [] 구간 별 이름 넣기
# 0< <=40 / 40< <=50 / 50< <=100
age_group = pd.cut(data2['Age'], bins =[0, 40, 50, 100] , labels = ['young','junior','senior'])
# 0<= <40 / 40<= <50 / 50<= <100 으로 하려면 right = False
age_group = pd.cut(data2['Age'], bins =[0, 40, 50, 100] , labels = ['young','junior','senior'], right = False)
- 데이터 프레임 결합 두 가지
1. pd.concat()
: 매핑 기준: 인덱스(행), 칼럼이름(열)
2. pd.merge()
: 매핑 기준: 특정 칼럼(key)의 값 기준으로 결합
DB의 Join과 같음
- concat
: axis = 0 세로로 합치기(행이 늘어남) / axis = 1 가로로 합치기(열이 늘어남)
join = ‘outer’ 모든 행과 열 합치기 / join = ‘inner’ 매핑되는 행과 열만 합치기
ex) pop = pd.concat([pop01, pop02], join = ‘outer’, axis = 1)
- merge
: 키 값을 기준으로 병합 가능
pd.merge(df1, df2, how = ‘inner / outer’, on = key_value)
ex) pop = pd.merge(pop1, pop2, how = ‘inner’, on = ‘year)
- pivot
: 집계된 데이터를 재구성할 때 쓰임
dataframe.pivot(index, cloumns, values)
** dataframe을 groupby후 pivot table 만들 수 있음
ex) temp3 = temp2.pivot('Category', 'Date' ,'Qty')
- 시계열 데이터 (sequential data)
: 행과 행에 시간의 순서(흐름)가 있고 행과 행의 시간 간격이 동일한 데이터
데이터 처리(2)
- 날짜 요소 추출
1. 날짜 타입으로 변환
pd.to_datetime(날짜데이터, format = ‘입력되는 날짜 형식’)
ex) pd.to_datetime(날짜데이터, format = ‘%d/%m/%Y’)
Y = 2023 / y = 23
date.dt.year : 연도
date.dt.month : 월
date.dt.day : 일
date.dt.weekday : 요일 (0: 월, 6: 일)
date.dt.day_name() : 요일 이름
- 시계열 데이터
: 행과 행에 시간 순서(흐름)이 있고 시간 간격이 동일한 데이터
shift(), rolling.mean(), .diff() 는 시계열 데이터 일 때만 사용 가능
1. shift()
: 시계열 데이터에서 시간의 흐름 전후로 정보를 이동시킬 때 사용
.shift(1) -> 어제 데이터를 땡겨 온다 (1이 default)
.shift(2) -> 엊그제 데이터를 땡겨 온다
2. .rolling().mean()
: 시간의 흐름에 따라 일정 기간 동안 평균을 이동하면서 구하기
df[‘tmp’].rolling(3).mean() -> 오늘 포함 3일의 평균을 구해줌
df[‘tmp’].rolling(3, min_periods = 1).mean()
-> 오늘 포함 3일동안 데이터가 1개 있더라도 구해와!
3. .diff() (= 차분)
: 특정 시점 데이터, 이전 시점 데이터와의 차이 구하기
.diff(2) -> 자기 값과 전전 값과의 차이
CRISP-DM
- Business Understanding – 가설 수립
: 문제를 정의하고 요인을 파악하기 위해서 가설을 수립한다.
1. 귀무가설
: 기존 연구 결과로 이어져 내려오는 정설을 귀무가설이라 한다.
2. 대립가설
: 기존의 입장을 넘어서기 위한 새로운 연구 가설을 대립가설이라 한다.
가설 수립 절차
1. 해결해야 할 문제가 무엇인가? (목표, 관심사,y)
2. Y를 설명하기 위한 요인을 찾기 (x)
3. 가설의 구조를 정의하기 (x->y)
- Data Understanding
: 데이터 원본 식별 및 취득
1. 있는 데이터: 가공해서 그대로 사용
2. 없는 데이터: 취득 가능, 취득 불가능
데이터 탐색방법: EDA, CDA
1. EDA (Exploratory Data Analysis -> 탐색적 데이터 분석)
- 개별 데이터의 분포, 가설이 맞는지 파악
- NA, 이상치 파악
- 그래프, 통계량
2. CDA (Confirmatory Data Analysis -> 확증적 데이터 분석)
- 탐색으로 파악하기 애매한 정보는 통계적 분석도구(가설검정) 사용
- 가설검정, 실험
- Data Preparation
: 모든 셀에 값이 있어야 한다. : NaN 조치
모든 값이 숫자이어야 한다. : 범주 -> 숫자 변환(가변수화)
값의 범위를 일치시켜야 한다. : 스케일링
-> 결측치 조치, 가변수화, 스케일링, 데이터분할
- Modeling
: 중요 변수들을 선택하고, 적절한 알고리즘으ㄹ적용하여 예측 모델 생성
- Evaluation
: 모델에 대한 데이터 분석 목표와 비즈니스 목표달성에 대한 평가
- 데이터 시각화
: 데이터를 그래프(시각화)로 한 눈에 파악 가능
-> 통계적인 해석을 넘어 비즈니스 인사이트를 파악하는 것이 중요
한계점
1. 그래프와 통계량에는 요약된 정보(원본)가 표현 된다.
2. 요약을 하는 관점에 따라 해석의 결과가 달라진다
3. 요약을 하면 정보의 손실이 발생한다.
- 시각화 라이브러리
: matplotlib와 seaborn 패키지
- 차트 그리기
: plt.plot(1차원 값)
x축: 인덱스
y축: 1차원 값
- plt.plot(x축, y축)
plt.plot(data['Date'], data['Temp'])
plt.plot('Date', 'Temp', data = data)
- 차트 꾸미기
1. 차트 x축, y축, 타이틀 붙이기
plt.xticks(rotation = 30) # x축 값 꾸미기 : 방향을 30도 틀어서
plt.xlabel('Date') # x축 이름 지정
plt.ylabel('Ozone') # y축 이름 지정
plt.title('Daily Airquality') # 타이틀
2. color
'red','green','blue' ... 혹은 'r', 'g', 'b', ...
3. linestyle
'solid', 'dashed', 'dashdot', 'dotted'
혹은 '-' , '--' , '-.' , ':'
4. marker
"." point
"," pixel
"o" circle
"v" triangle_down
"^" triangle_up
"<" triangle_left
">" triangle_right
5. 범례, 그리드 추가
label = ‘범례이름’ -> 범례 추가
plt.legend(loc = ‘upper right’ -> 레이블 표시하기
# label = : 범례추가를 위한 레이블값
plt.plot(data['Date'], data['Ozone'], label = 'Ozone')
plt.plot(data['Date'], data['Temp'], label = 'Temp')
# 레이블 표시하기. loc = : 위치
plt.legend(loc = 'upper right')
# 데이터 시각화 예시
plt.plot(data['Date'], data['Ozone'], color='green', linestyle='dotted', marker='o')
- df.plot()
-> 데이터프레임에 plot쓰기
data.plot(x = ‘Date’, y = [‘Temp’, ‘Ozone’], title = ‘abcd’)
plt.grid()
plt.show()
- 여러 그래프 나눠서 그리기
:plt.subplot(row, cloumn, index)
row, colum -> 그래프 행 열
index -> 그래프 순서
- 개별 변수 분석(단변량 분석)
그래프 | 통계량 | |
숫자형 | - 히스토그램(도수분포표) - 밀도함수그래프(kde plot) (도수분포표) - box plot(기초 통계량) |
- min, max, mean, std - 사분위수 |
범주형 | - bar plot | - 범주별 빈도수 - 범주별 비율 |
1. 숫자형 변수
(1) 숫자로 요약하기: 정보의 대푯값(평균, 중앙값(median()), 최빈값(mode), 사분위수)
-> df.describe()로 확인 가능
-> 기초 통계량
(2) 구간을 나누고 빈도수 계산: 도수 분포표 ex) 10대, 20대,...
-> 도수분포표
- 평균
- 산술 평균: 모든 값들을 더한 후 개수로 나눈 수
- 조화 평균: 분자가 동일한 두 비율의 평균
- 사분위수
: 데이터를 오름차순으로 정렬한 후, 전체를 4등분하고 각 경계값에 해당되는 값 (25,50,75%)
- 히스토그램
plt.hist(df[‘칼럼명’], bins = 구간수)
sns.histplot(x=’컬럼명’, data = 데이터이름, bins = 구간수)
단점: 구간 bin의 너비를 어떻게 잡냐에 따라 모양이 다름
- 밀도함수 그래프(kde plot)
: seaborn 라이브러리로 그림 (sns.kedplot())
밀도함수 그래프 아래 면적 = 1
- boxplot
: 값에 NaN이 있으면 그래프가 그려지지 않음
plt.boxplot(df[‘컬럼명’], vert = False) # vert = False -> 가로로 그려줌
min ~ 1사분위수 / 1사분위수 ~ 2사분위수 / 2사분위수 ~ 3사분위수 / 3사분위수 ~ max
왼쪽 펜스 값 = min과 (1사 - 1.5 * IQR) 중 큰 값
오른쪽 펜스 값 = max와 (1사 + 1.5 * IQR) 중 작은 값
** IQR = Q3-Q1
2. 범주형 변수
- 범주별 빈도수
Series.value_counts()
titanic[‘Embarked’].value_counts()
- 범주별 비율
df.shape -> (행의 수, 열의 수)
titanic[‘Embarked’].value_counts() / titanic.shape[0]
- bar plot
: sns.countplot(df[‘컬럼명’])
plt.bar(df[‘컬럼명’].value_counts())
temp = titanic['Embarked'].value_counts()
print(temp.index, temp.values)
plt.bar(x = temp.index, height = temp.values)
plt.show()
데이터 분석(1)
Y | |||||
숫자 | 범주 | ||||
그래프 | 통계량 | 그래프 | 통계량 | ||
X | 숫자 | - 산점도 (scatter) | - 상관분석 - 상관계수 |
- kde plot - box plot - histogram - density plot |
- 숫자를 범주로 또는 범주를 숫자로 바꾸어서 통계량 측정 |
범주 | - barplot | - 범주 2개 : T-test - 범주 3개 : ANOVA |
- mosaic | - 카이제곱 검정 |
- 단변량 분석 종합 실습 진행
: 카시트 판매량 데이터의 구조와 통계량을 알아보고, 시각화까지 하여 카세트 판매량과 상관관계가 있는지, 없는지 각 데이터에 대해 해석하는 시간을 가졌다. 각 데이터마다의 통계량과 시각화 하는데에는 큰 어려움이 없었지만 실제로 통계량과 시각화된 그래프를 보고 카세트 판매량과 어떤 상관관계가 있을까 하는 생각하는 것이 쉽지 않았다.
**가로로 출력하기 팁**
# .T를 붙이면 가로로 출력된다.
display(df[['컬럼명']].describe().T)
Y | |||||
숫자 | 범주 | ||||
그래프 | 통계량 | 그래프 | 통계량 | ||
X | 숫자 | - 산점도 (scatter) | - 상관분석 - 상관계수 |
||
범주 | - barplot | - 범주 2개 : T분석 - 범주 3개 : ANOVA |
[ 이변량분석 (숫자 -> 숫자) ]
<시각화>
1. 산점도(Scatter)
: 점으로 이루어진 그래프 (점들이 얼마나 직선으로 이루어졌는가)
-> y = ax+b로 얼마나 잘 표현되었는가가 강한관계인지 아닌지 알 수 있음
plt.scatter(df[‘컬럼명’], df[‘컬럼명’])
plt.scatter(‘컬럼명’, ‘컬럼명’, data = df)
sns.scatterplot(x=’컬럼명’, y=’컬럼명‘, data = df)
# 한번에 산점도 그리기
sns.pairplot(df)
# 산점도+히스토크램 같이 그리기
sns.jointplot(x = ‘컬럼명’, y = ‘컬럼명’, data = df)
# 산점도 + 직선 같이 그리기
sns.regplot(x = ‘컬럼명’, y = ‘컬럼명’, data = df)
<통계량>
1. 공분산, 상관계수
: 각 점들이 얼마나 직선에 모여있는지 계산
- 상관계수(r)
: 관계를 수치화 (-1~1 사이 값)
-1,1에 가까울수록 강한 상관관계를 나타냄
- 상관분석
: 상관계수가 유의미한지를 검정
- 상관계수와 상관분석
import scipy.stats as spst
spst.pearsonr(df[‘컬럼명’], df[‘컬럼명’])
# 결과: (상관계수, p-value) 튜플로 결과 나옴
# 상관계수가 1이어도 기울기는 다양함 즉, 상관계수는 기울기와는 상관없음
# 직선이 아닌 패턴은 분석할 수 없음, 즉, 상관계수는 직선의 관계(선형관계)만 수치화
# ** 주의: NaN이 있으면 계산되지 않음 -> .notnull() **
# 결측치 잇는지 아는 방법
df.info()
df.isna().sum()
- p-value
: 유의미한지를 판단하는 숫자(유의 확률)
판단기준(유의수준)
p-value < 0.05 -> 관계 있다 (상관계수가 의미 있다)
p-value >= 0.05 -> 관계 없다 (상관계수가 의미 없다)
- df.corr()
: dataframe의 모든 숫자형 변수 상호간에 상관계수 계산
[ 이변량분석 (범주 -> 숫자) ]
범주가 2개: 두 평균의 차이 비교
범주가 3개: 전체 평균과 각 범주의 평균 비교
<시각화>
- 평균
1. 분산(Var), 표준편차(SD)
: 값들이 평균으로부터 얼마나 벗어나 있는지를 나타내는 값(이탈도, deviation)
- 전수조사
: 정확한 평균, but 시간,비용 많이 든다
- 표본조사
: 충분히 많은 표본을 뽑아 평균, but 오차 발생
표본을 뽑는 목적 -> 모집단 추정
ㄴ 표본평균
:모 평균에 대한 추정치, 오차가 존재(표준오차)
- sns.barplot
: 평균 값을 비교하는 그래프
두 평균의 차이가 크고, 신뢰구간은 겹치지 않을 때, 대립가설이 맞다고 봄.
-> 즉, 대립가설이 맞으려면 평균 차이가 많이 나야함
sns.barplot(x = ‘컬럼명’, y = ‘컬럼명’, data= df)
# plt.barplot과 sns.countplot과 다름
# plt.barplot – 막대 그래프
# sns.countplot – 카테고리 값별로 데이터가 얼마나 있는지
<통계량>
- T-test
- t 통계량
: 두 그룹의 평균 간 차이를 표준오차로 나눈값
두 평균의 차이로 이해해도 좋음
-2보다 작거나 2보다 크면 차이가 있다
p-value가 0.05보다 작으면 차이가 있다
# NaN 행 제외
temp = df.loc[df[‘컬럼명’].notnull()]
변수1 = temp.loc[temp[‘범주컬럼명’] == 조건, ‘수치컬럼명’]
변수2 = temp.loc[temp[‘범주컬럼명’] == 조건2, ‘수치컬럼명’]
spst.ttest_ind(변수1, 변수2)
# 변수1-변수2 이므로 양수면 변수1이 크고 음수면 변수2가 큼
# t통계량 값이 클수록 평균값 차이가 큼
- ANOVA (ANalysis Of VAriance) 분산 분석
: 범주가 3개 이상일 때 사용
1. F통계량 = 집단간 분산 / 집단 내 분산 = 전체평균-각집단평균 / 각집단의평균-개별값
-> 집단 내의 분산이 작고 집단간 분산이 클수록 F통계량이 크다
2. F분포
: F통계량 값이 2~3 이상이면 차이가 있다고 판단
# NaN 행 제외
temp = df.loc[df[‘컬럼명’].notnull()]
변수1 = temp.loc[temp[‘범주컬럼명’] == 조건, ‘수치컬럼명’]
변수2 = temp.loc[temp[‘범주컬럼명’] == 조건2, ‘수치컬럼명’]
변수3 = temp.loc[temp[‘범주컬럼명’] == 조건3, ‘수치컬럼명’]
spst.f_oneway(변수1, 변수2, 변주3)
# F통계량 값이 클수록 평균값 차이가 큼
# F통계량 값이 2~3 이상이면 차이가 있다고 판단
# 분산분석은 전체 평균대비 각 그룹간 차이만을 알려줌
# -> 어느 그룹 간 차이가 있는지 알 수 없음
데이터 분석(2)
Y | |||||
숫자 | 범주 | ||||
그래프 | 통계량 | 그래프 | 통계량 | ||
X | 숫자 | - 산점도 (scatter) | - 상관분석 - 상관계수 |
- kde plot - box plot - histogram - density plot |
- 숫자를 범주로 또는 범주를 숫자로 바꾸어서 통계량 측정 |
범주 | - barplot | - 범주 2개 : T-test - 범주 3개 : ANOVA |
- mosaic | - 카이제곱 검정 |
- 이변량 분석 실습
: 직원 이직에 영향을 끼치는 변수가 얼마나 영향을 끼치는지, 무슨 변수인지를 분석해보는 실습을 진행하였다. kdeplot으로 숫자->범주에 대한 시각화와 mosaic으로 범주->숫자에 대한 시각화도 해보았다. 범주->숫자에 대한 통계량 측정으로 카이제곱 검정도 실습해보았는데 어제 배웠던 내용보다 다소 어려웠다. 다른 경우와 다르게 숫자 -> 범주에 대한 통계량 측정은 숫자를 범주로 또는 범주를 숫자로 바꾸어서 숫자->숫자 라던지, 범주->범주로 바꾸어 통계량을 측정해야 한다는 것이 다른 경우의 통계량을 구하는 것과 차이가 있었다.
이변량 분석 (범주->범주)
<시각화>
- 교차표(crosstab)
pd.crosstab(행, 열, normalize = '')
# ** normalize = ‘columns’ or ‘index’ or ‘all’
# columns: 열 기준 합이 1인 비율로 나타내줌
# index: 행 기준 합이 1인 비율로 나타내줌
# all: 전체 기준 합이 1인 비율로 나타내줌
- mosaic plot
: 두 범주형 변수가 아무런 상관이 없다면 범주 별 비율 차이 없음
반대로 전체 평균 비율 선 기준으로 서로 오차가 크다면 상관관계 큼
# mosaic 라이브러리 불러오기
from statsmodels.graphics.mosaicplot import mosaic
# mosaic그리기
mosaic(df, [‘컬럼명1’,‘컬럼명2’])
axhline(1- df[‘컬럼명’].mean(), color = ‘r’) # 세로선 axvline
plt.show()
<통계량>
- 카이제곱 검정
: ((실제 관측빈도 – 기대빈도)^2 / 기대빈도) 의 합
클수록 기대빈도로부터 실제 값에 차이가 크다는 의미
범주의 수가 늘어날수록 값이 커짐
자유도의 약 2배 보다 크면 차이가 있다고 봄
# 교차표 만들기 (nomarlize하면 안됨)
변수1 = pd.crosstab(df[‘컬럼명1’], df[‘컬럼명2’])
# 카이제곱 검정
spst.chi2_contingency(변수1)
# 결과값
# 1 카이제곱 통계량
# 2 p-value
# 3 자유도
# 4 기대빈도: 계산된 값
- 자유도
: 범주의 수 – 1
ex) 4개의 범주라고 하면 차례대로 첫 번째부터 세 번째 까지는 선택할 수 있지만 마지막 범주는 선택권 x
-> 자유도 = 3
이변량 분석 (숫자->범주)
<시각화>
- sns.kdeplot()
# df의 컬럼명1을 컬럼명2로 구별해서 그리기
sns.kdeplot(x = ‘컬럼명1’, data = df, hue = ‘컬럼명2, common_norm = False)
# common_norm = True => 면적이 평균 비율대로 나옴
# common_norm = False => 면적을 1 기준으로 그려줌
# 색으로 채워진 그래프
sns.kdeplot(x = ‘컬럼명1’, data = df, hue = ‘컬럼명2, mutiple = ’fill’)
# 전체 평균선 긋기
plt.axhline(df[‘컬럼명’].mean(), color = ‘r’)
plt.show()
<통계량>
[숫자 -> 범주]의 통계량을 구하기 위해서는 숫자를 범주로 바꾸어 [범주 -> 범주] 또는 범주를 숫자로 바꾸어 [숫자 -> 숫자]로 바꾸어 통계량을 측정해야한다.