5minbetter commited on
Commit
d3e0045
·
1 Parent(s): 4267c4e

fix: 특정 직무/레벨 결측 데이터 및 에러 방어 로직 추가

Browse files
Files changed (1) hide show
  1. 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' : level_dict[f'L{final_level-1}']
169
  },
170
  'right' : {
171
- 'title' : "현재 레벨:" + f'L{final_level}',
172
- 'definition' : level_dict[f'L{final_level}']
173
  },
174
  }
175
  else:
176
  output = {
177
  'left' : {
178
  'title' : "현재 레벨: " + f'L{final_level}',
179
- 'definition' : level_dict[f'L{final_level}']
180
  },
181
  'right' : {
182
  'title' : "상위 레벨: " + f'L{final_level+1}',
183
- 'definition' : level_dict[f'L{final_level+1}']
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
- std_pool = float(np.std(job_pool_vals, ddof=1))
235
- mean_job = float(np.mean(job_pool_vals))
 
 
 
 
 
 
 
 
 
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
- level = label.split(': ')[1]
 
 
378
  table = target_table[['평가요소', level]].copy()
379
  table, chart = format_table(table, user_score, level)
380
  pages.append({
381
- "title": label.split(': ')[0],
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)