[빅데이터분석기사] 실기 대비 3일차 - 기출문제 3회
본 글은 개인적으로 공부하려고 작성한 내용입니다.
만일 저작권 및 다른 이유로 인해 문제가 발생할 소지가 있다면
pental@kakao.com 으로 메일 또는 해당 게시물에 댓글을 달아주시면 처리하도록 하겠습니다.
본 내용은 빅데이터분석기사-2차실기 / 장은진 교수님의 강의를 듣고 개인적으로 추가 공부가 필요한 내용에 대해서 정리한 글입니다.
작업형 1유형 문제 1
주어진 데이터 중 컬럼들의 결측값을 전부 제거한 후 데이터를 처음부터 순서대로 70%를 추출하여 housing_median_age 컬럼의 1분위수를 산출해라.
(단, 출력 결과는 정수형태로 한다.)
import pandas as pd
df = pd.read_csv("./bigdata_csvfile/california_housing.csv")
display(df.head())
longitude latitude housing_median_age total_rooms total_bedrooms population households median_income median_house_value ocean_proximity
0 -122.23 37.88 41.0 880.0 129.0 322.0 126.0 8.3252 452600.0
1 -122.22 37.86 21.0 7099.0 1106.0 2401.0 1138.0 8.3014 358500.0
2 -122.24 37.85 52.0 1467.0 190.0 496.0 177.0 7.2574 352100.0
3 -122.25 37.85 52.0 1274.0 235.0 558.0 219.0 5.6431 341300.0
4 -122.25 37.85 52.0 1627.0 280.0 565.0 259.0 3.8462 342200.0
pd를 통해서 데이터를 읽어온다. california_housing.csv 파일.
이 켈리포니아 하우스 데이터는 어디서나 쓰이는거 같은데,,, 좀더 분석해두면 좋을 것 같다.
먼저 문제에서 결측값을 전부 제거하라 했기 때문에 `.isnull()` 함수를 통해서 결측값을 모두 제거한다. 먼저 결측값의 데이터를 확인한다.
print(df.isnull().sum())
longitude 0
latitude 0
housing_median_age 0
total_rooms 0
total_bedrooms 207
population 0
households 0
median_income 0
median_house_value 0
ocean_proximity 0
dtype: int64
데이터 분석 결과 total_bedrooms 컬럼에서 207개의 결측값이 확인 되었다. 이 값을 모두 날리기 위해서 .dropna() 함수를 통해서 결측값을 제거한다.
df = df.dropna(axis = 0)
print(df.isnull().sum())
longitude 0
latitude 0
housing_median_age 0
total_rooms 0
total_bedrooms 0
population 0
households 0
median_income 0
median_house_value 0
ocean_proximity 0
dtype: int64
현재 위 isnull 결과와 같이 결측값이 모두 삭제 된것을 확인 하루 수 있으며, 전체 데이터의 갯수를 확인하기 위해서 len() 함수를 통해 확인하였다.
print(len(df)) # 전체 : 20433
전체 행 갯수는 20433개로 확인되었으며 아래와 같이 70%로 나누기 위해서 전체 행 * 0.7을 통해서 70%의 행을 계산했다.
print(len(df) * 0.7) # 70% 행 : 14303.09999999
70% 행을 슬라이싱 하기 위해서 iloc을 통해 14303개의 행만 따로 분리 후 quantile을 통해서 1분위수를 산출한다.
df = df.iloc[:14303, :]
print(int(df['housing_median_age'].quantile(0.25))) # 19
답 : 19
작업형 1유형 문제 2
4개년도 (2000, 2006, 2012, 2021)에 대한 국가별 기아의 수치 데이터에서 2000년 전체 기아 수치의 평균을 구하고, 2000년 데이터를 대상으로 연산된 평균보다 큰 값을 갖는 국가의 수를 산출하시오
df = pd.read_csv("./bigdata_csvfile/global_hunger_data.csv")
display(df.head())
Entity Code Year Global Hunger Index
0 Afghanistan AFG 2000
1 Afghanistan AFG 2006
2 Afghanistan AFG 2012
3 Afghanistan AFG 2021
4 Albania ALB 2000
기아의 수치 데이터에서 2000년 전체 기아수치의 평균을 구하기 위해서 다음과 같이 조건식을 세운다.
조건식을 세우고 `Global Hunger Index` 컬럼의 평균을 계산한다.
cond = df['Year'] == 2000
hunger_avg = (df[cond]['Global Hunger Index'].mean())
print(hunger_avg) # 24.439285714285717
이 결과 24.439285714285717라는 수치가 나왔으며 이 값은 hunger_avg 변수에 저장한다.
평균을 구했기 때문에 2000년 이며 평균 수치보다 큰 국가의 갯수를 계산하기 위해서 다음과 같이 조건식 2개를 세운다.
cond1 = df['Year'] == 2000
cond2 = df['Global Hunger Index'] > hunger_avg
print(len(df[cond1 & cond2])) # 50
답 : 50
다른 풀이로는 다음과 같이 짤수 있다.
# 다른 답안
df = pd.read_csv("./bigdata_csvfile/global_hunger_data.csv")
df.sort_values('Year', ascending = True, inplace = True)
data_2000 = df.loc[df['Year'] == 2000]
mean = data_2000['Global Hunger Index'].mean()
# print(mean)
result = data_2000['Entity'].loc[data_2000['Global Hunger Index'] > mean].size
print(result)
작업형 1유형 문제 3
주어진 데이터의 컬럼별로 결측값들의 비율을 확인하여 결측값의 비율이 가장 높은 변수명을 출력하시오
df = pd.read_csv("./bigdata_csvfile/titanic.csv")
display(df.head())
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN
결측값을 확인하기 위해서 isnull() 함수를 사용했다.
print(df.isnull().sum())
PassengerId 0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64
print(df.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Name 891 non-null object
4 Sex 891 non-null object
5 Age 714 non-null float64
6 SibSp 891 non-null int64
7 Parch 891 non-null int64
8 Ticket 891 non-null object
9 Fare 891 non-null float64
10 Cabin 204 non-null object
11 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None
info의 갯수에서 총 891개의 행이 존재하며, cabin 컬럼에서는 687개의 결측값이 존재한다고 한다.
이러면 답은 Cabin 컬럼에서 결측값이 제일 많이 때문에 Cabin 컬럼이 정답이다.
age_data = (sum(df['Age'].isna()) / 891) * 100
print(age_data) # 19.865319865319865
cabin_data = (sum(df['Cabin'].isna()) / 891) * 100
print(cabin_data) # 77.10437710437711
embarked_data = (sum(df['Embarked'].isna()) / 891) * 100
print(embarked_data) # 0.22446689113355783
작업형 2유형
다음은 여행객 정보 데이터를 기반으로 여행보험 상품가입 여부(TravelInsurance)가 1일 확률을 예측하시오.
단, 평가지표는 roc_auc_score로 하고, 제출 파일의 컬름은 cust_id(인덱스 번호), Insurance(가입여부) 두 개만 존재해야 하며, 제출 파일 이름은 3rd_test_type2.csv로 한다.
train = test3_type2_train.csv
test = test3_type2_test.csv
먼저 train과 test 데이터를 불러온다.
import pandas as pd
train = pd.read_csv("./bigdata_csvfile/test3_type2_train.csv")
test = pd.read_csv("./bigdata_csvfile/test3_type2_test.csv")
기본적으로 EDA 를 진행하여, 결측값, 이상치 등을 모두 확인한다.
print(train.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1490 entries, 0 to 1489
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ID 1490 non-null int64
1 Age 1490 non-null int64
2 Employment Type 1490 non-null object
3 GraduateOrNot 1490 non-null object
4 AnnualIncome 1490 non-null int64
5 FamilyMembers 1490 non-null int64
6 ChronicDiseases 1490 non-null int64
7 FrequentFlyer 1490 non-null object
8 EverTravelledAbroad 1490 non-null object
9 TravelInsurance 1490 non-null int64
dtypes: int64(6), object(4)
memory usage: 116.5+ KB
None
print(test.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 497 entries, 0 to 496
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ID 497 non-null int64
1 Age 497 non-null int64
2 Employment Type 497 non-null object
3 GraduateOrNot 497 non-null object
4 AnnualIncome 497 non-null int64
5 FamilyMembers 497 non-null int64
6 ChronicDiseases 497 non-null int64
7 FrequentFlyer 497 non-null object
8 EverTravelledAbroad 497 non-null object
dtypes: int64(5), object(4)
memory usage: 35.1+ KB
None
print(train.isnull().sum())
ID 0
Age 0
Employment Type 0
GraduateOrNot 0
AnnualIncome 0
FamilyMembers 0
ChronicDiseases 0
FrequentFlyer 0
EverTravelledAbroad 0
TravelInsurance 0
dtype: int64
print(test.isnull().sum())
ID 0
Age 0
Employment Type 0
GraduateOrNot 0
AnnualIncome 0
FamilyMembers 0
ChronicDiseases 0
FrequentFlyer 0
EverTravelledAbroad 0
dtype: int64
결측값도 이상이 없고, 다른 특이적인 EDA는 발견되지 않았기에 학습 준비를 시작한다. 문제에서도 주어졌듯이 `roc_auc_score`를 사용하라 했으며, 분류 확률을 예측하는 모델을 생성하는 것이다. 이 말은 즉슨, 분류를 사용하라는 것이다.
`train.info()` 결과에서 `object`타입으로 되어 있는 데이터들의 `value_counts`를 계산해 보았다.
cols = ["Employment Type", "GraduateOrNot", "FrequentFlyer", "EverTravelledAbroad"]
for col in cols :
print(train[col].value_counts())
Employment Type
Private Sector/Self Employed 1061
Government Sector 429
Name: count, dtype: int64
GraduateOrNot
Yes 1262
No 228
Name: count, dtype: int64
FrequentFlyer
No 1185
Yes 305
Name: count, dtype: int64
EverTravelledAbroad
No 1207
Yes 283
Name: count, dtype: int64
각각의 컬럼에서는 0 또는 1로 분류될수 있는 데이터들로 이루어져있기 때문에 sklearn의 preprocessing의 LabelEncoder를 사용한다.
from sklearn.preprocessing import LabelEncoder
for col in cols :
le = LabelEncoder()
le.fit(train[col])
train[col] = le.transform(train[col])
for col in cols :
le = LabelEncoder()
le.fit(test[col])
test[col] = le.transform(test[col])
중요한 점은 train데이터에 라벨인코딩을 할 경우, test 데이터에도 동일하게 라벨인코딩을 진행해주어야한다.
이부분에서 잘못됐다. train과 test를 합치고 라벨인코딩하고 다시 합쳤어야했다고 한다.
그리고 종속변수와 독립변수를 나눈다.
from sklearn.model_selection import train_test_split
X = train.drop(columns = ["TravelInsurance"])
y = train['TravelInsurance']
train_test_split 함수를 통해서 X_train, X_test, y_train, y_test를 나누고, RandomForestClassifier을 통해서 분류를 진행한다.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 123)
print(X_train.shape, X_test.shape, y_train.shape, y_test. shape)
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier(n_estimators = 200, max_depth = 25, random_state = 123)
rfc.fit(X_train, y_train)
pred = rfc.predict_proba(X_test)[:, 1]
from sklearn.metrics import roc_auc_score
roc = roc_auc_score(y_test, pred)
print(roc)
(1192, 9) (298, 9) (1192,) (298,)
0.8137515644555694
81%라는 높은 정확도를 가지고 있으며, 여기서 중요한점은 1일 확률을 계산하라 했기 때문에 `predict_proba`를 통해서 예측하였다.
이때 진짜 중요한점은 `predict(X_test)`와 달리 `predict_proba(X_test)[:, 1]`이 되어야 한다.
그 이유는 `predict_proba`는 이딴식으로 되어 있기 때문,,, 아마 0일 확률을 계산하라 했으면 `[:, 0]` 이 되어야 할것이다.
array([[0.875 , 0.125 ],
[0.71 , 0.29 ],
[0.89 , 0.11 ],
[0.9 , 0.1 ],
[0.69 , 0.31 ],
[0.82 , 0.18 ],
pred = rfc.predict_proba(test)[:, 1]
pd.DataFrame(
{
'cust_id' : test.index,
'insurance' : pred
}
).to_csv("3rd_test_type2.csv", index = False)
print(pd.read_csv("3rd_test_type2.csv").head())
cust_id insurance
0 0 0.240
1 1 0.260
2 2 0.345
3 3 0.135
4 4 0.415
train데이터로 진행을 했으니 test데이터로 마지막 과정을 진행한다.
test.index 메모.