04. Job and Salaries in Data Science
출처: https://www.kaggle.com/datasets/hummaamqaasim/jobs-in-data
Jobs and Salaries in Data Science
Salary Trends in Data-Related Careers
www.kaggle.com
1. 데이터 불러오기
'데이터'와 관련된 직종의 임금 트렌드를 나타낸 데이터로, (9355, 12)의 크기를 갖고 있다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
#데이터 불러오기
df = pd.read_csv('/kaggle/input/jobs-in-data/jobs_in_data.csv')
df.head()
#데이터 수 확인
df.shape
#데이터 기본정보 확인
df.info()
#데이터 기초통계 확인
df.describe()
데이터를 간단하게 살펴봤을 때, target은 'salary_in_usd'로 global 기준에 표준화된 수치를 설정했다. 그 외 결측치는 존재하지 않았다.
먼저 캐글에서 제공하고 있는 데이터의 특성을 살펴보았다.
- work_year: 데이터가 저장된 년도 / 년도에 따라, 금액 차이가 있을 것 같다는 가설. 데이터 분포로 보고 제거여부 판단
- job_title: 직업 역할 / 카테고리 변수로 라벨 인코더를 진행할 예정
- job_category: 직업에 대한 더 넓은 카테고리 / job_title의 상위 그룹으로, VIF 발생 가능성 有
- salary_currency: usd, eud 등 어떤 기준으로 급여가 지불됐는지 / 제거 예정
- salary: Target이지만, eud, usd로 차이가 있음 / 제거 예정
- salary_in_usd: USD로 표준화한 salary. Target으로 선정
- employee_residence: 거주지 / 거주지에 따라 임금의 차이가 있을까? 가설
- experience_level: 숙련도 / 급여에 큰 영향을 줄 것이다
- employment_type: 직책 / 풀타임, 알바 등 급여에 큰 영향
- work_setting: 원격, 오프라인, 하이브리드 / 급여에 큰 영향, 하지만 직책과 연관성이 있을까?
- company_location: 회사가 어디에 위치하는지 / employee_residence와 다중공선성 가능성 있을 듯
- company_size: 회사규모 / 급여에 큰 영향을 줄 것이다
2. EDA
본격적으로 데이터를 시각화하고 분석하면서 살펴보았다.
work_year의 데이터 불균형이 지나치게 심했다. 2023년에 80%이상 집중된 것을 확인했다.
급여와의 관계를 봤을 때, 2023년에 데이터가 주로 분포되어있고 급여의 관계도 모호했다.
다음으로 'job_title'과 'job_category'를 살펴봤을 때, 둘 중, 하나의 피쳐를 활용하는 게 낫겠다는 판단을 했다.
df[df['job_category'] == 'Data Engineering'].nunique()
work_year 4
job_title 15
job_category 1
salary_currency 8
salary 567
salary_in_usd 654
employee_residence 36
experience_level 4
employment_type 4
work_setting 3
company_location 32
company_size 3
예를 들어, 'job_category'가 'Data Engineering'인 경우의 'job_title'은 15개였고, 다른 카테고리를 선택했을 때, 겹치는 'job_title'이 없었다. 따라서 'job_category'만을 활용하기로 했다.
하지만 'job_category' 역시 데이터의 불균형이 있었다. 따라서 개수가 적은 데이터들을 others로 묶는 게 낫다고 판단하여 상위 4종을 제외한 나머지를 합친 'others'라는 값으로 변경했다.
jc = df['job_category'].value_counts()
plt.plot(len(range(jc)), jc)
df['job_category'] = df['job_category'].apply(lambda s: s if s not in jc[4:] else 'others')
상위 4종을 제외한 나머지는 'others'로 변경하였다.
다음으로 'employee residence' 또한 매우 불균형한 모습을 보여줬는데 미국이 전체의 약 90%를 차지하고 있었다.
우선은 미국을 제외한 나머지 국가를 하나로 묶고, 급여와의 관계를 살펴보았다.
others와 united states의 관계가 유의미하다고 판단되었다. 다만, 데이터 불균형은 여전히 문제였고, 성능이 좋지 않으면 제거하기로 하였다.
다음으로 근무 형태의 경우, 'Hybrid'타입이 애매하게 분포되어 있었고, 큰 영향을 주지 않을 것으로 생각했다. 실제로 시각화했을 때, 급여의 관계에서 제거해도 된다고 판단해 제거하였다.
예상했던 대로, company location은 거주지와 밀접한 연관이 있어 제거하였다.
회사 규모와 급여에는 관계가 있어보인다.
3. 데이터 전처리(피처 엔지니어링)
먼저 제거할 피쳐를 선정해 drop 하고, 라벨 인코더로 범주형 컬럼을 수치화시켜주는 과정을 거쳤다.
drop_cols = ['work_year', 'job_title', 'salary_currency', 'employment_type', 'company_location']
df.drop(drop_cols, axis = 1, inplace = True)
from sklearn.preprocessing import LabelEncoder
cat_cols = ['job_category', 'employee_residence', 'experience_level','work_setting', 'company_size']
le = LabelEncoder()
for col in cat_cols:
df[col] = le.fit_transform(df[col])
그 후, target을 y에, 나머지 독립변수를 X에 할당했다.
X = df
y = X.pop('salary_in_usd')
4. 모델 학습
모델학습을 하기 위해 test size를 30%로 설정 하였다.
학습 모델은 RandomForestRegressor, XGBRegressor, LGBMRegressor 세 자리 모델을 구축했고, 별다른 하이퍼 파라미터 튜닝은 하지 않았다.
from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(X, y, test_size = 0.3, random_state = 123)
from sklearn.ensemble import RandomForestRegressor
model_rf = RandomForestRegressor(random_state = 123)
model_rf.fit(X_tr, y_tr)
from xgboost import XGBRegressor
model_xgb = XGBRegressor(random_state = 123)
model_xgb.fit(X_tr, y_tr)
from lightgbm import LGBMRegressor
model_lgb = LGBMRegressor(random_state = 123)
model_lgb.fit(X_tr, y_tr)
5. 모델 평가
MAE와 RMSE로 모델 평가를 진행했다.
from sklearn.metrics import mean_absolute_error, mean_squared_error
pred_rf = model_rf.predict(X_val)
pred_xgb = model_xgb.predict(X_val)
pred_lgb = model_lgb.predict(X_val)
print("="*30, "MAE", "="*30)
print("RF: ", mean_absolute_error(y_val, pred_rf))
print("XGB: ", mean_absolute_error(y_val, pred_xgb))
print("LGB: ", mean_absolute_error(y_val, pred_lgb))
print("="*30, "RMSE", "="*30)
print("RF: ", np.sqrt(mean_squared_error(y_val, pred_rf)))
print("XGB: ", np.sqrt(mean_squared_error(y_val, pred_xgb)))
print("LGB: ", np.sqrt(mean_squared_error(y_val, pred_lgb)))
============================== MAE ==============================
RF: 1020.2242258307224
XGB: 1515.4012052556818
LGB: 1459.4000790375555
============================== RMSE ==============================
RF: 8355.655264796871
XGB: 9169.455960181487
LGB: 7904.714393549175
'파이썬 데이터분석' 카테고리의 다른 글
[03] Wine Dataset for Clustering (1) | 2024.01.20 |
---|---|
[02] Real Estate Dataset (0) | 2024.01.18 |
[01] Apple Quality (0) | 2024.01.18 |