지난 포스팅에서는 근무시간이 업무성과에 미치는 영향도를 분석하였습니다. 제 데이터로는 영향을 미치지 않는다고 결론이 나서 "칼퇴"의 정당성이 확보되었는데... 그럼 "일찍 일어나는 새가 벌레를 잡는다"라는 속담처럼 회사에 일찍출근하면 업무 효율이 높아져서 성과에도 영향을 미친다는 어르신들의 말씀에 데이터적 근거로 반론을... 제기해보고 싶다는 생각이 문들 들었네요.
그래서 이번 포스팅에서는 "출근시간" 을 기준으로 업무성과를 분석할 것인데, 이번 분석은 의사결장나무(Decision Tress)로 분석을 하려합니다. 독립변수를 "출근시간","근무시간" 이렇게 두가지로 분석할 것입니다.
의사결정나무(Decision Tree)
의사결정나무는 데이터를 분류하거나 예측하는데 사용되는 트리(Tree)형태의 분석 방법입니다. 데이터를 조건에 따라 여러 단계로 나누어, 쉽게 해석 가능한 의사결정 구조를 생성하는 것입니다.
예를들어 아래와 같이 날씨에 따른 운동 여부를 판단하는 나무(Tree)를 만들 수 있겠지요.
날씨가 맑음인가?
├── Yes → 온도가 높나?
│ ├── Yes → 🚫 운동 안함
│ └── No → ✅ 운동 함
└── No → 바람이 강한가?
├── Yes → 🚫 운동 안함
└── No → ✅ 운동 함
의사결정나무의 가장 큰 장점은 "해석이 쉽고 직관적", "변수의 중요도를 쉽게 확인"," 데이터의 사전 처리(정규화,표준화)가 필요 없다는 장점이 있지만 항상 주의 해야 할 것은 과적합(Overfitting) 가능성입니다. 나무가 복잡해지면 훈련 데이터에 지나치게 최적화되어 새로운 데이터에 대한 예측이 떨어질 수 있기 때문입니다.
Python Code : 의사결정나무 (Decision Tree)
Step1) 라이브러리 임포트
import pandas as pd
from sklearn.tree import DecisionTreeRegressor, plot_tree
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt
- pandas : 데이터 처리 라이브러리
- DecisionTreeRegressor, plot_tree : 의사결정나무 모델 생성 및 시각화
- train_test_split : 데이터를 학습과 평가용으로 분리
- mean_squared_error, r2_score : 모델 성능 평가를 위한 지표
- matplotlib : 데이터 시각화를 위한 라이브러리
Step2) 데이터 로딩 (엑셀 파일 읽기)
df_hours = pd.read_excel(r'C:\Users\shjung\Desktop\개인\python\예제1.xlsx') # 사번, 근무시간
df_arrival = pd.read_excel(r'C:\Users\shjung\Desktop\개인\python\예제2.xlsx') # 사번, 출근시간 등급
df_ratings = pd.read_excel(r'C:\Users\shjung\Desktop\개인\python\예제.xlsx') # 사번, 업무평가등급
- 세 가지 엑셀 파일에서 데이터를 불러옵니다.
- r을 붙여 경로 오류를 방지하는 Raw 문자열을 사용했습니다.
Step3) 데이터 병합 (Merge)
df = pd.merge(df_hours, df_arrival, on='사번', how='inner')
df = pd.merge(df, df_ratings, on='사번', how='inner')
- 세 가지 데이터의 공통된 컬럼(사번) 기준으로 Join을 합니다.
- Inner 조인방식은 모든 데이터에서 공통으로 존재하는 사번만을 사용해서 병합을 하는 의미입니다. (Outer 일경우는 기준이 되는 문서의 모든 사번에 대한 병합이 이루어집니다. 이때는 근무시간, 출근시간 파일에 해당 사번이 없을 경우 Null 값이 되기에 분석에 적합하지 않습니다.)
Step4) 독립변수(X), 종속변수(y) 설정
X = df[['근무시간', '출근시간']]
y = df['등급']
- 독립변수(X) : 예측 또는 설명을 위해 사용되는 변수(근무시간, 출근시간)
- 종속변수(y) : 우리가 예측하고자 하는 대상(등급)
Step5) 데이터 훈련/테스트 데이터로 분리
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
- 데이터 전체를 랜덤하게 80% 훈련(학습) 과 20% 테스트(평가) 로 나눕니다.
- random_state=42 : 같은 결과를 얻기 위한 설정(재현성 보장)
Step6) 의사결정나무 모델 생성 및 학습
tree_model = DecisionTreeRegressor(max_depth=3, random_state=42)
tree_model.fit(X_train, y_train)
- DecisionTreeRegressor로 회귀형 의사결정나무 모델 생성
- 과적합(overfitting)을 방지를 위해 Max_depth를 3으로 설정합니다.
- tree_model.fit은 훈련 데이터를 이용해 모델을 학습(fit)합니다.
Step7) 테스트 데이터로 예측 수행
y_pred = tree_model.predict(X_test)
- 학습된 모델을 기반으로 테스트 데이터에 대한 평가등급을 예측합니다.
Step8) 모델 성능 평가
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"의사결정나무 평균제곱오차(MSE): {mse:.3f}")
print(f"의사결정나무 결정계수(R²): {r2:.3f}")
- 평균제곱오차(MSE) : 실제값과 예측값 사이의 평균 오차 크기 (작을수록 좋음)
- 결정계수(R²) : 모델의 설명력 (1에 가까울수록 좋음)
- 이 결과로 모델의 예측 정확성을 평가할 수 있습니다.
Step9) 변수 중요도 출력
importances = tree_model.feature_importances_
feature_importance_df = pd.DataFrame({'변수': X.columns, '중요도': importances})
print(feature_importance_df.sort_values(by='중요도', ascending=False))
- 각 변수 (근무시간, 출근시간)가 평가등급 예측에 얼마나 중요한지를 수치로 나타냅니다.
- 변수 중요도(feature importance) 가 높을수록 모델에서 더 중요한 역할을 합니다.
Python Code : 의사결정 나무 분석결과
제곱오차(MSE)는 예측값과 실제값 간의 평균 제곱 오차입니다. MSE가 0에 가까울수록 모델의 예측이 정확하다는 의미이므로,0.299는 비교적 큰 오차입니다.
결정계수(R²)는 모델의 종속변수(등급)의 분산을 얼마나 설명하는지를 나타냅니다. 일반적으로 0~1 사이 값이 나오지만, 음수가 나왔다는 것은 "모델이 평균값으로 예측하는 것보다 못한 수준" 이라는 뜻에 가깝습니다. 즉 근무시간, 출근시간은 등급을 전혀 설명할 수 없다는 의미이지요.
변수 중요도는 전체 분할과정에서 "출근시간" 만 사용되었고 그 비중이 100% 라는 뜻입니다. 제곱 오차는 크고 결정계수는 낮은데 근무시간은 전혀고려대상도 아니였다는 것이지요..
의사결정나무 시각화
plt.figure(figsize=(14,10))
plot_tree(tree_model, feature_names=['근무시간', '출근시간 등급'], filled=True, rounded=True)
plt.title('의사결정나무 시각화', fontsize=16)
plt.show()
출근시간 등급 <=0.825를 기준으로 True 가지쪽은 출근시간이 빠른 직원 그룹내에서, 근무시간이 길거나 짧은지에 따라 평가 등급이 서로 다르게 나타나는 경향이 있음을 표기합니다. 즉 "출근시간이 빠르다 = 등급이 높다" 라는 단순한 공식이 성립하지 않고, 근무시간 및 출근시간 등급의 세부 수준에 따라 평가 등급이 다르게 분포합니다. 출근시간은 빠르고 근무시간이 높을때 등급 (Value)가 1.65로 가장 높습니다. 다만 이경우는 False 쪽의 Value 값과 비교하여 낮기에 공식이 성립하지 않습니다.
출근시간 등급 <=0.825를 기준으로 False 일경우 출근시간이 늦을 경우, 전반적으로 등급이 상승하는 경향이 있습니다. 다만 마지막 노드에서는 오차범위(Squared_error)가 가장 크게 나타납니다. 이는 결국 출근시간이 무조건 늦는다고 등급이 계속 상흥하는 것은 아님을 나타냅니다.
결론
테스트 예제를 기반으로 모델 검증을 하였을 때 결과값을 해석하면 " 출근시간이 늦어지면, 어느정도 평가 등급이 상승"하는 경향이 있으나, 일정 수준(출근시간 >1.974)를 넘어서면 더 이상 그 관계가 일관되지 않으며 예측오차도 증가하여 근무시간, 출근시간 모두 등급을 결정하는 상관관계를 설명할 수 없습니다(영향을 주지 않는다는 것이지요).
단순이 "출근시간","근무시간"의 독립변수만으로 검증을 하였지만, 더 많은 독립변수를 두고 검증을 하면 평가등급에 영향을 미치는 요소를 찾을 수 있을 것입니다.
이젠..일찍출근하는 것이! 오래 근무하는 것이! 성과(업무평가)와 전혀 관계 없음이 증명되었다~ Cheers
참고: 전체코드
import pandas as pd
from sklearn.tree import DecisionTreeRegressor, plot_tree
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Malgun Gothic' # Windows용
# plt.rcParams['font.family'] = 'AppleGothic' # MacOS용
# plt.rcParams['font.family'] = 'NanumGothic' # Linux용 또는 설치된 경우
plt.rcParams['axes.unicode_minus'] = False # 마이너스(-) 기호 깨짐 방지
# 데이터 로딩
df_hours = pd.read_excel(r'C:\Users\shjung\Desktop\개인\python\예제1.xlsx') # 사번, 근무시간
df_arrival = pd.read_excel(r'C:\Users\shjung\Desktop\개인\python\예제2.xlsx') # 사번, 출근시간 등급
df_ratings = pd.read_excel(r'C:\Users\shjung\Desktop\개인\python\예제.xlsx') # 사번, 업무평가등급
# 데이터 병합
df = pd.merge(df_hours, df_arrival, on='사번', how='inner')
df = pd.merge(df, df_ratings, on='사번', how='inner')
# 독립변수(X), 종속변수(y)
X = df[['근무시간', '출근시간']]
y = df['등급']
# 데이터를 훈련 데이터와 테스트 데이터로 분할 (80:20 비율)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 의사결정나무 모델 생성 및 학습 (나무 깊이 최대 3으로 제한)
tree_model = DecisionTreeRegressor(max_depth=3, random_state=42)
tree_model.fit(X_train, y_train)
# 테스트 데이터로 예측
y_pred = tree_model.predict(X_test)
# 모델 성능 평가
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"의사결정나무 평균제곱오차(MSE): {mse:.3f}")
print(f"의사결정나무 결정계수(R²): {r2:.3f}")
# 의사결정나무 시각화
plt.figure(figsize=(14,10))
plot_tree(tree_model, feature_names=['근무시간', '출근시간 등급'], filled=True, rounded=True)
plt.title('의사결정나무 시각화', fontsize=16)
plt.show()
# 변수 중요도 출력
importances = tree_model.feature_importances_
feature_importance_df = pd.DataFrame({'변수': X.columns, '중요도': importances})
print(feature_importance_df.sort_values(by='중요도', ascending=False))
'IT > Python 데이터 분석 활용' 카테고리의 다른 글
[회귀분석] 근무시간이 업무성과에 미치는 영향 분석 (1) | 2025.06.18 |
---|---|
[Python] 데이터 전처리 (1) | 2025.05.17 |
[Python] 시각화 plot() (Matplotlib,Pandas) (1) | 2024.06.04 |
[Python] Pandas[판다스] 활용하기(2) (0) | 2024.05.30 |
[Python] Pandas[판다스] 활용하기(1) (0) | 2024.05.29 |
댓글