결측치 채우기
train : Age(나이) , Embarked(승선항구), Cabin(객실번호)
test : Age(나이) , Fare(요금), Cabin(객실번호)
단순 기술통계치로 값을 채우는 것보다 각 컬럼의 특성을 파악해서 채우는 것이 좋다 => 다른 컬럼들과 상관관계를 확인하여 결측치를 채워보자
# 기술통계량 확인
train['Age'].describe()
train['Cabin'].describe()
# 조건을 줘서 행에 접근하는 인덱싱 방법을 통해 B96, B95 행을 출력해보자
# boolean 불리언 인덱싱
# train[조건] => 조건이 참인 값들만 출력을 해준다
train['Cabin'] == 'B96 B98' #조건
train[train['Cabin'] == 'B96 B98']
pd.set_option('display.max_rows',None) # None(전체출력) : 내가 보고싶은 개수
train['Embarked'].describe()
# 탑승항구 : S , Q , C
# Embarked 컬럼에서 S 값을 가지는 승객들(행), 데이터를 출력해보자
train[train['Embarked'] == 'S']
데이터 전처리
Age 컬럼의 결측치를 채우기
그냥 나이 데이터 라고 했을때 가장 먼저 떠올리는 방법이 평균값
분포를 확인했을때 다른 컬럼들과의 상관관계를 이용하여 결측치를 채워본다
# train 데이터 를 기준으로 상관관계 확인 .corr()
# 분포에 따른 상관관계를 이해한다.
# 1 ~ -1 범위를 갖는다 : 0에 가까울수록 상관관계가 없어진다.
train.corr()
# 수치형 데이터들만 출력 됨
# Age 컬럼과의 가장 높은 상관관계를 가지는 컬럼은 Pclass
Age 데이터와 높은 상관관계를 가지는 Pclass 값을 사용할건데 생존에 관련이 높았던 성별데이터도 함께 가져와서 나이값을 채운다.
# 피벗테이블 그려보기 : 컬럼들의 요약된 정보를 출력해줌(테이블 형태)
pt1 = train.pivot_table(values ='Age', # 데이터로 사용될 컬럼 이름
index = ['Pclass','Sex'], # 데이터 요약시 사용되는 컬럼이름
aggfunc = 'mean') # 각 그룹별로 어떤 값을 조회할건지
pt1
# 각 컬럼별로 여성 남성에 따른 나이 평균값이 출력이 됨
# 결측치를 채울때 전체 평균보다는 관련있는 컬럼들로 세분화를 하여 채우면 오차 줄어듬
# 다중 인덱싱 / 멀티 인덱싱 => 두개 이상의 인덱스가 있을때 값 가져오는 방법
# df.loc[(인덱스1,인덱스2),열]
# 21.75 값에 접근하고싶다. => Pclass 3 등급, Sex : 여자
pt1.loc[(3,'female'),'Age']
# 2등급이면서 남자의 나이 출력
pt1.loc[(2,'male'),'Age']
#1등급이면서 여성인 사람의 나이 출력
pt1.loc[(1,'female'),'Age']
Age 컬럼의 결측치를 채워주는 함수를 만들어서 apply 명령으로 한번에 적용시키기
사용자정의함수를 먼저 정의 하고 apply 함수를 사용
apply : 행 또는 열에 특정함수를 일괄적으로 적용시키는 함수
#age 결측치를 처리하는 함수 정의하기
def fill_age (data): # 매개변수 data는 train 이나 test가 들어간다
if pd.isna(data['Age']):# 데이터에 있는 값이 null값이라면
# 만약 Age컬럼에 결측치가 있다면 피벗테이블에서 값 가져와
# 멀티인덱싱 결과
return pt1.loc[(data['Pclass'],data['Sex']),'Age']
else : # 결측치가 없다면 나이값을 그대로 가져와
return data['Age'] # 원래 Age 컬럼의 데이터
# apply 함수를 사용하여 전체 Age 컬럼에 적용
# apply(함수이름, axis = 0 or 1)
train['Age'] = train.apply(fill_age,axis= 1).astype('int64')
train['Age']
# apply 함수는 apply 함수 앞에 있는 데이터를 매개변수로 넣어준다
# 여기서는 train 이 data 가 되는것
#astype : 데이터의 타입을 변경해주는 함수(나이를 정수로 표기)
# test 데이터 나이 결측치 채우기
test['Age'] = test.apply(fill_age,axis= 1).astype('int64')
test['Age']
# train, test 피벗테이블은 개별로 가지고있어야 하지만
# (다운받은 데이터여서)데이터간의 큰 차이가 존재하지 않아 그냥 진행
# train 과 test 데이터를 합친 전체 데이터에서 만든 피벗테이블이 가장 좋다
train-Embarked 결측치 처리하기
# Embarked 정보 확인
train['Embarked'].value_counts()
test['Embarked'].value_counts()
# 결측치가 너무 적으면 가장 많은 값으로 넣어도 크게 영향을 미치지않는다
#fillna(지정값) : 우리가 지정해준 값으로 결측치를 전부 채워주는 함수
#다시 대입을 해야 적용된다.✔✔✔✔
train['Embarked'] = train['Embarked'].fillna('S')
test-Fare 결측치 채워주기
test['Fare'].value_counts()
test['Fare'].describe()
# 차이가 너무 나서 피벗테이블사용
# 신뢰성 중요
#Fare 컬럼의 상관관계확인
test.corr()
pt2 = test.pivot_table(values ='Fare', # 데이터로 사용될 컬럼 이름
index = ['Pclass','Sex'], # 데이터 요약시 사용되는 컬럼이름
aggfunc = 'mean') # 각 그룹별로 어떤 값을 조회할건지
pt2
# 비어있는 값이 1개니까 함수사용 X
# test ['Fare'] 결측치 행을 출력 => 값 삽입 (결측치가 1개니까 가능)
# boolean 불리언 인덱싱
test[test['Fare'].isnull()]
# Pclass가 3등급이고 Sex 남자인 요금의 평균값을 넣는다. = 11.826350
test['Fare']=test['Fare'].fillna(11.826350)
# Age결측치 채우는 것과 같은 원리
Cabin 결측치 처리(train, test 둘다 결측치 존재)
Cabin 컬럼은 실제 있는 데이터보다 결측치가 더 많이 존재
컬럼을 삭제 / 결측치에 임의의 값을 넣어서 시각화한다음 결측치간의 패턴 확인
# 결측치 개수 확인
train['Cabin'].isnull().value_counts()
# Cabin 데이터 중복값 없이 출력
train['Cabin'].unique()
# 전체적으로 데이터 중복이 없음
# 이 데이터에서 우리가 활용할 수 있는 방법 고안
# 알파벳의 특정패턴 파악
데이터 개수에 비해 중복없는 값이 너무 많을때(데이터 얇고 넓게 분포)
객실 번호에서 의미있는 알파벳만 가져와서 활용
# Cabin 컬럼의 결측치들을 임의의 알파벳인 'M' 을 채운후 확인
# 임의의 컬럼을 추가해서 데이터 파악에 혼동없도록한다.
train['Deck']=train['Cabin'].fillna('M')
test['Deck']=test['Cabin'].fillna('M')
# 결측치 값의 패턴확인을 위한 임의의 데이터 대입(시각화)
#확인
display(train.head(3))
# 데이터에서 제일 앞에 있는 알파벳 값만 가져와서 활용
# 문자열에서 맨앞부분 가져오기
train['Deck']=train['Deck'].str[0]
test['Deck']=test['Deck'].str[0]
# train, test 데이터에서 기존 Cabin 컬럼 삭제 (drop)
train.drop('Cabin',axis=1,inplace=True)#axis =1 (columns), 0 (index)
test.drop('Cabin',axis=1,inplace=True)
# 결측치 해결 (전처리과정 끝)
# Deck / Survived / Name 컬럼을 사용해서 피벗테이블 생성
# Name 값 value 로 가지고 각 Deck의 개수를 세어준다.
pt3 = train.pivot_table(values ='Name', # 데이터로 사용될 컬럼 이름
index = ['Deck','Survived'], # 데이터 요약시 사용되는 컬럼이름
aggfunc = 'count') # 각 그룹별로 어떤 값을 조회할건지
pt3
# seaborn 그래프 그려주기
sns.countplot(data = train,
x = 'Deck', # x축에 Deck 컬럼의 unique 한 값을 축으로 설정
hue = 'Survived')# unique 값에 따라 각각 차트가 생성되고 구분해주는 값
# Pclass에 따른 생존여부 확인
sns.countplot(data = train,
x = 'Pclass',
hue = 'Survived')
# Deck / Pclass 동시에 시각화
sns.countplot(data = train,
x = 'Deck',
hue = 'Pclass')
# 결측치(M)에 3등급사람이 많았다.
# Sex, Embarked 시각화
sns.countplot(data = train,
x = 'Sex',
hue = 'Survived')
sns.countplot(data = train,
x = 'Embarked',
hue = 'Survived')
sns.countplot(data = train,
x = 'Sex',
hue = 'Embarked')
Age 컬럼 수치화 (수치형 데이터) 막대그래프 X
plt.figure(figsize=(15,5))
sns.countplot(data = train,
x = 'Age',
hue = 'Survived')
# 바이올린 플롯 : 바이올린 형태로 데이터의 분포와 밀도를 보기쉽게 곡선형태로 출력
# 데이터 많은곳 두꺼움, 적게 분포 얇게
sns.violinplot(data = train,
x = 'Sex',
y = 'Age',
hue = 'Survived')
plt.grid()
# 20~40대 탑승자가 많아서 사망도 많이함
# 수치값(실수) 같이 연속된 데이터의 경우 모두 유니크 하게 값을 표현하기가 어려움
# 곡선형태의 분포를 나타내주는 바이올린 플롯을 활용하여 분포를 확인하면 좋다
# 정확한 수치파악(연속적인값)을 위해 사용
sns.violinplot(data = train,
x = 'Sex',
y = 'Fare',
hue = 'Survived',
split = True)
plt.grid()