|
| 1 | +import pandas as pd |
| 2 | +import numpy as np |
| 3 | +import json |
| 4 | +import requests |
| 5 | +import unicodedata |
| 6 | +from copy import deepcopy |
| 7 | + |
| 8 | + |
| 9 | +def json_to_dataframe(language = "py"): |
| 10 | + ''' |
| 11 | + json 형태인 데이터를 불러와 사전 처리를 거친 후 |
| 12 | + '언어별' 알고리즘 풀이 데이터를 반환합니다. |
| 13 | +
|
| 14 | + Args: |
| 15 | + language (str): 언어 구분 ('py' | 'js'), default 'py' |
| 16 | +
|
| 17 | + Returns: |
| 18 | + data (DataFrame): json 에서 DataFrame으로 변환된 '언어별' 테이블 데이터 |
| 19 | + ''' |
| 20 | + |
| 21 | + data_path = "https://raw.githubusercontent.com/Algorithm-Coding-Test-Data-Analysis/algoview/main/dataAnalysis/macro/data.json" |
| 22 | + resp = requests.get(data_path) |
| 23 | + data_json = json.loads(resp.text) |
| 24 | + |
| 25 | + data_json = file_name_exception(data_json) |
| 26 | + df = json_to_df(data_json) |
| 27 | + df = split_data_into_py_js(df, language) |
| 28 | + |
| 29 | + return df |
| 30 | + |
| 31 | +def unicode_err(df): # 회사명, 문제유형, 문제이름 중복 오류 |
| 32 | + |
| 33 | + ''' |
| 34 | + unicodedata.normalize() 함수는 문자열에 있는 유니코드 문자를 |
| 35 | + NFKC형식(문자열을 표준 호환성(KC) 형식으로 정규화)으로 정규화합니다. |
| 36 | + problem_name, problem_type, company_name 컬럼의 값 중 같은 값을 |
| 37 | + 파이썬에서 다르게 인식하는 문제를 해결합니다. |
| 38 | + |
| 39 | + Args: |
| 40 | + data : (DataFrame | Series) |
| 41 | +
|
| 42 | + Returns: |
| 43 | + data : (DataFrame | Series) |
| 44 | + ''' |
| 45 | + |
| 46 | + df["company_name"] = df['company_name'].apply(lambda x: unicodedata.normalize('NFKC', x)) |
| 47 | + df["problem_type"] = df['problem_type'].apply(lambda x: unicodedata.normalize('NFKC', x)) |
| 48 | + return df |
| 49 | + |
| 50 | + |
| 51 | +def prob_type_to_etc(value): # 문제 유형이 아닌 카테고리를 "기타"로 분류 (추후 제거 될 수 있는 기능) |
| 52 | + |
| 53 | + ''' |
| 54 | + 오류로 인해 실제 문제 유형이 아닌 값들을 예외 처리 |
| 55 | + 추후 추가 혹은 삭제 될 수 있습니다. |
| 56 | + |
| 57 | + Args: |
| 58 | + data : (DataFrame | Series) |
| 59 | +
|
| 60 | + Returns: |
| 61 | + data : (DataFrame | Series) |
| 62 | + ''' |
| 63 | + |
| 64 | + err_list = [ # 추후 err_list 종류가 늘어나는 것을 대비, 혹은 문제 유형 list를 만들어 비교하여 제거 |
| 65 | + '에라토스테네스의체', |
| 66 | + ] |
| 67 | + if value in err_list: |
| 68 | + return "기타" |
| 69 | + else: |
| 70 | + return value |
| 71 | + |
| 72 | + |
| 73 | +def file_name_exception(json_file): |
| 74 | + err_list_path = "https://raw.githubusercontent.com/Algorithm-Coding-Test-Data-Analysis/algoview/main/dataAnalysis/excluded_list.txt" |
| 75 | + res = requests.get(err_list_path) |
| 76 | + err_list = res.text.split("\n")[2:-1] |
| 77 | + |
| 78 | + print("예외 처리 전 json 파일 길이: ", len(json_file)) |
| 79 | + |
| 80 | + for error_file in err_list: |
| 81 | + try: |
| 82 | + del json_file[error_file] |
| 83 | + except KeyError: |
| 84 | + pass |
| 85 | + |
| 86 | + print("예외 처리 후 json 파일 길이: ", len(json_file)) |
| 87 | + |
| 88 | + return json_file |
| 89 | + |
| 90 | + |
| 91 | +def split_data_into_py_js(data, lang = "py"): # Python, JavaScript로 data 분리 |
| 92 | + |
| 93 | + ''' |
| 94 | + 전체 데이터인 DataFrame을 입력 받아 |
| 95 | + Pytho과 JavaScript 별로 데이터를 분리 |
| 96 | +
|
| 97 | + Args: |
| 98 | + data (DataFrame): DataFrame으로 변환된 data |
| 99 | + language (str): 언어 구분 |
| 100 | +
|
| 101 | + Returns: |
| 102 | + 언어별 데이터 (DataFrame) |
| 103 | + ''' |
| 104 | + |
| 105 | + print("-"*5, "split into python DataFrame & js DataFrame","-"*5) |
| 106 | + |
| 107 | + df = data.copy() |
| 108 | + if lang == "py": |
| 109 | + py_df = df[df["file_name"].str.contains(".py")].reset_index(drop = True) |
| 110 | + print("python DataFrame 길이: {0}".format(len(py_df))) |
| 111 | + return py_df |
| 112 | + |
| 113 | + elif lang == "js": |
| 114 | + js_df = df[df["file_name"].str.contains(".js")].reset_index(drop = True) |
| 115 | + print("js DataFrame 길이: {0}".format(len(js_df))) |
| 116 | + return js_df |
| 117 | + |
| 118 | + |
| 119 | +def json_to_df(json_file): # methodcount 와 method명을 분리하기 위함 |
| 120 | + |
| 121 | + ''' |
| 122 | + json 형태인 데이터를 입력 받아 |
| 123 | + DataFrame으로 변환 |
| 124 | + ‘function_method’ column 안에 method 와 module이 함께 집계됩니다. |
| 125 | +
|
| 126 | + Args: |
| 127 | + data : (json) |
| 128 | +
|
| 129 | + Returns: |
| 130 | + data : (DataFrame) |
| 131 | + ''' |
| 132 | + |
| 133 | + data_json = deepcopy(json_file) |
| 134 | + df = pd.DataFrame() # empty DataFrame |
| 135 | + for file_name in data_json.keys(): |
| 136 | + temp_df = pd.DataFrame(data_json[file_name]) |
| 137 | + temp_df = temp_df.reset_index() |
| 138 | + df = pd.concat([df, temp_df], axis = 0) |
| 139 | + |
| 140 | + temp_df_len = len(temp_df) # countmethod가 0인 파일 사전 처리 후 concat |
| 141 | + if temp_df_len == 0: |
| 142 | + temp_df = pd.DataFrame(data_json[file_name], index = [0]).reset_index() |
| 143 | + df = pd.concat([df, temp_df], axis = 0) |
| 144 | + |
| 145 | + df = df.reset_index(drop = True).rename(columns = {"index" : "function_method"}) # method명 column으로 변환 |
| 146 | + df = df[['file_name', 'level', 'year', 'company_name','problem_name', 'problem_type', # column 순서 재배치 |
| 147 | + 'function_method', 'countmethod', 'module', 'check_user_class', 'line_count', 'code']] |
| 148 | + |
| 149 | + df = df.fillna(np.nan) |
| 150 | + df = unicode_err(df) # 회사명, 문제유형, 문제이름 중복 오류 |
| 151 | + df["problem_type"] = df["problem_type"].apply(lambda x: prob_type_to_etc(x)) # 문제 유형이 아닌 카테고리를 "기타"로 분류 |
| 152 | + df["company_name"] = df["company_name"].apply(lambda x: prob_type_to_etc(x)) # 문제 유형이 아닌 카테고리를 "기타"로 분류 |
| 153 | + df = df.drop(df.loc[df["code"] == "",:].index).reset_index(drop = True) |
| 154 | + df["check_user_class"] = df["check_user_class"].astype("int").astype("category") |
| 155 | + |
| 156 | + return df |
| 157 | + |
| 158 | + |
| 159 | + |
| 160 | + |
| 161 | + |
0 commit comments