Spaces:
Running
Running
Commit ·
d3e0045
1
Parent(s): 4267c4e
fix: 특정 직무/레벨 결측 데이터 및 에러 방어 로직 추가
Browse files- core/core.py +30 -10
core/core.py
CHANGED
|
@@ -121,6 +121,9 @@ def get_final_level(user_score, level_range, factors):
|
|
| 121 |
final_level = level
|
| 122 |
break
|
| 123 |
|
|
|
|
|
|
|
|
|
|
| 124 |
low_set = s[s < final_level].sort_values().index.tolist()
|
| 125 |
middle_set = s[(s >= final_level) & (s < final_level+1)].sort_values().index.tolist()
|
| 126 |
high_set = s[s >= final_level].sort_values(ascending=False).index.tolist()
|
|
@@ -161,26 +164,32 @@ def judge_level(user_score, level_range, job):
|
|
| 161 |
final_level, max_level, guides = get_final_level(user_score, level_range, factors)
|
| 162 |
|
| 163 |
level_dict = level_def[level_def['직무'] == job].set_index('수준')['수준 정의']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
if final_level == max_level:
|
| 165 |
output = {
|
| 166 |
'left' : {
|
| 167 |
-
'title' : "하위 레벨:" + f'L{final_level-1}',
|
| 168 |
-
'definition' :
|
| 169 |
},
|
| 170 |
'right' : {
|
| 171 |
-
'title' : "현재 레벨:" + f'L{final_level}',
|
| 172 |
-
'definition' :
|
| 173 |
},
|
| 174 |
}
|
| 175 |
else:
|
| 176 |
output = {
|
| 177 |
'left' : {
|
| 178 |
'title' : "현재 레벨: " + f'L{final_level}',
|
| 179 |
-
'definition' :
|
| 180 |
},
|
| 181 |
'right' : {
|
| 182 |
'title' : "상위 레벨: " + f'L{final_level+1}',
|
| 183 |
-
'definition' :
|
| 184 |
},
|
| 185 |
}
|
| 186 |
|
|
@@ -231,8 +240,17 @@ def judge_wage(
|
|
| 231 |
job_pool_df = raw_df[(raw_df['ITSQF 직무(변환)'] == job)&(raw_df['ITSQF 수준'] == final_level)]
|
| 232 |
job_pool_vals = pd.to_numeric(job_pool_df[base_type], errors="coerce").dropna().to_numpy(dtype=float)
|
| 233 |
|
| 234 |
-
|
| 235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
|
| 237 |
# 2) cohort (직무 + 레벨 + 옵션 필터)
|
| 238 |
def get_cohort_df(df, bm, sales, emp):
|
|
@@ -374,11 +392,13 @@ def generate_dataset(request_options, user_choice):
|
|
| 374 |
pages = []
|
| 375 |
charts = []
|
| 376 |
for label in definitions.loc['title'].tolist():
|
| 377 |
-
|
|
|
|
|
|
|
| 378 |
table = target_table[['평가요소', level]].copy()
|
| 379 |
table, chart = format_table(table, user_score, level)
|
| 380 |
pages.append({
|
| 381 |
-
"title":
|
| 382 |
"table": [table]
|
| 383 |
})
|
| 384 |
charts.append(chart)
|
|
|
|
| 121 |
final_level = level
|
| 122 |
break
|
| 123 |
|
| 124 |
+
# 최종 판정 레벨이 직무의 지원 레벨 범위를 벗어나지 않도록 클리핑 방어
|
| 125 |
+
final_level = max(min_level, min(max_level, final_level))
|
| 126 |
+
|
| 127 |
low_set = s[s < final_level].sort_values().index.tolist()
|
| 128 |
middle_set = s[(s >= final_level) & (s < final_level+1)].sort_values().index.tolist()
|
| 129 |
high_set = s[s >= final_level].sort_values(ascending=False).index.tolist()
|
|
|
|
| 164 |
final_level, max_level, guides = get_final_level(user_score, level_range, factors)
|
| 165 |
|
| 166 |
level_dict = level_def[level_def['직무'] == job].set_index('수준')['수준 정의']
|
| 167 |
+
|
| 168 |
+
def get_level_definition(level_str):
|
| 169 |
+
if level_str in level_dict.index:
|
| 170 |
+
return level_dict[level_str]
|
| 171 |
+
return f"{job} {level_str} 수준에 대한 상세 정의가 데이터베이스에 존재하지 않습니다."
|
| 172 |
+
|
| 173 |
if final_level == max_level:
|
| 174 |
output = {
|
| 175 |
'left' : {
|
| 176 |
+
'title' : "하위 레벨: " + f'L{final_level-1}',
|
| 177 |
+
'definition' : get_level_definition(f'L{final_level-1}')
|
| 178 |
},
|
| 179 |
'right' : {
|
| 180 |
+
'title' : "현재 레벨: " + f'L{final_level}',
|
| 181 |
+
'definition' : get_level_definition(f'L{final_level}')
|
| 182 |
},
|
| 183 |
}
|
| 184 |
else:
|
| 185 |
output = {
|
| 186 |
'left' : {
|
| 187 |
'title' : "현재 레벨: " + f'L{final_level}',
|
| 188 |
+
'definition' : get_level_definition(f'L{final_level}')
|
| 189 |
},
|
| 190 |
'right' : {
|
| 191 |
'title' : "상위 레벨: " + f'L{final_level+1}',
|
| 192 |
+
'definition' : get_level_definition(f'L{final_level+1}')
|
| 193 |
},
|
| 194 |
}
|
| 195 |
|
|
|
|
| 240 |
job_pool_df = raw_df[(raw_df['ITSQF 직무(변환)'] == job)&(raw_df['ITSQF 수준'] == final_level)]
|
| 241 |
job_pool_vals = pd.to_numeric(job_pool_df[base_type], errors="coerce").dropna().to_numpy(dtype=float)
|
| 242 |
|
| 243 |
+
# 데이터가 비어있는 경우(Empty data pool)에 대한 Fallback 방어 코드
|
| 244 |
+
if job_pool_vals.size == 0:
|
| 245 |
+
print(f"[WARN] Empty data pool for Job={job}, Level={final_level}. Falling back to Level={final_level} all jobs.")
|
| 246 |
+
job_pool_df = raw_df[raw_df['ITSQF 수준'] == final_level]
|
| 247 |
+
job_pool_vals = pd.to_numeric(job_pool_df[base_type], errors="coerce").dropna().to_numpy(dtype=float)
|
| 248 |
+
if job_pool_vals.size == 0:
|
| 249 |
+
print(f"[WARN] No data at all for Level={final_level}. Falling back to all raw data.")
|
| 250 |
+
job_pool_vals = pd.to_numeric(raw_df[base_type], errors="coerce").dropna().to_numpy(dtype=float)
|
| 251 |
+
|
| 252 |
+
std_pool = float(np.std(job_pool_vals, ddof=1)) if job_pool_vals.size >= 2 else 0.0
|
| 253 |
+
mean_job = float(np.mean(job_pool_vals)) if job_pool_vals.size >= 1 else 0.0
|
| 254 |
|
| 255 |
# 2) cohort (직무 + 레벨 + 옵션 필터)
|
| 256 |
def get_cohort_df(df, bm, sales, emp):
|
|
|
|
| 392 |
pages = []
|
| 393 |
charts = []
|
| 394 |
for label in definitions.loc['title'].tolist():
|
| 395 |
+
parts = [p.strip() for p in label.split(':')]
|
| 396 |
+
title_prefix = parts[0]
|
| 397 |
+
level = parts[1]
|
| 398 |
table = target_table[['평가요소', level]].copy()
|
| 399 |
table, chart = format_table(table, user_score, level)
|
| 400 |
pages.append({
|
| 401 |
+
"title": title_prefix,
|
| 402 |
"table": [table]
|
| 403 |
})
|
| 404 |
charts.append(chart)
|