콘텐츠로 이동

hossam.my_qtcheck

hossam.my_qtcheck

set_type

set_type(
    data,
    as_int=[],
    as_float=[],
    as_string=[],
    as_category=[],
    as_datetime=[],
)

데이터프레임의 컬럼 타입을 변경하고 변경된 데이터프레임의 정보를 출력하는 함수

Parameters:

Name Type Description Default
data DataFrame

타입을 변경할 데이터프레임

required
as_int list

int 타입으로 변경할 컬럼 리스트

[]
as_float list

float 타입으로 변경할 컬럼 리스트

[]
as_string list

string 타입으로 변경할 컬럼 리스트

[]
as_category list

category 타입으로 변경할 컬럼 리스트

[]
as_datetime list

datetime 타입으로 변경할 컬럼 리스트

[]

Returns:

Name Type Description
DataFrame

타입이 변경된 데이터프레임

Source code in hossam/my_qtcheck.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def set_type(data, as_int=[], as_float=[], as_string=[], 
             as_category=[], as_datetime=[]):
    """
    데이터프레임의 컬럼 타입을 변경하고 
    변경된 데이터프레임의 정보를 출력하는 함수

    Args:
        data (DataFrame): 타입을 변경할 데이터프레임
        as_int (list): int 타입으로 변경할 컬럼 리스트
        as_float (list): float 타입으로 변경할 컬럼 리스트
        as_string (list): string 타입으로 변경할 컬럼 리스트
        as_category (list): category 타입으로 변경할 컬럼 리스트
        as_datetime (list): datetime 타입으로 변경할 컬럼 리스트

    Returns:
        DataFrame: 타입이 변경된 데이터프레임
    """
    df = data.copy()

    for col in as_int:
        df[col] = df[col].astype(int)
    for col in as_float:
        df[col] = df[col].astype(float)
    for col in as_string:
        df[col] = df[col].astype(str)
    for col in as_category:
        df[col] = df[col].astype('category')
    for col in as_datetime:
        df[col] = to_datetime(df[col])

    df.info()

    return df

get_number_column_names

get_number_column_names(data)

데이터프레임에서 숫자형 컬럼의 이름을 리스트로 반환하는 함수

Parameters:

Name Type Description Default
data DataFrame

숫자형 컬럼의 이름을 추출할 데이터프레임

required

Returns:

Name Type Description
list

숫자형 컬럼의 이름 리스트

Source code in hossam/my_qtcheck.py
39
40
41
42
43
44
45
46
47
48
49
def get_number_column_names(data):
    """
    데이터프레임에서 숫자형 컬럼의 이름을 리스트로 반환하는 함수

    Args:
        data (DataFrame): 숫자형 컬럼의 이름을 추출할 데이터프레임

    Returns:
        list: 숫자형 컬럼의 이름 리스트
    """
    return data.select_dtypes(include="number").columns.to_list()

get_categorical_column_names

get_categorical_column_names(data)

데이터프레임에서 범주형 컬럼의 이름을 리스트로 반환하는 함수

Parameters:

Name Type Description Default
data DataFrame

범주형 컬럼의 이름을 추출할 데이터프레임

required

Returns:

Name Type Description
list

범주형 컬럼의 이름 리스트

Source code in hossam/my_qtcheck.py
51
52
53
54
55
56
57
58
59
60
61
def get_categorical_column_names(data):
    """
    데이터프레임에서 범주형 컬럼의 이름을 리스트로 반환하는 함수

    Args:
        data (DataFrame): 범주형 컬럼의 이름을 추출할 데이터프레임

    Returns:
        list: 범주형 컬럼의 이름 리스트
    """
    return data.select_dtypes(include="category").columns.to_list()

check_duplicates

check_duplicates(data, drop=True)

데이터프레임에서 행 단위 중복을 검사하고, 중복된 행을 제거하는 함수

Parameters:

Name Type Description Default
data DataFrame

중복을 검사할 데이터프레임

required
drop bool

중복된 행을 제거할지 여부 (기본값: True)

True

Returns:

Name Type Description
DataFrame

중복이 제거된 데이터프레임

Source code in hossam/my_qtcheck.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
def check_duplicates(data, drop=True):
    """
    데이터프레임에서 행 단위 중복을 검사하고, 중복된 행을 제거하는 함수

    Args:
        data (DataFrame): 중복을 검사할 데이터프레임
        drop (bool): 중복된 행을 제거할지 여부 (기본값: True)

    Returns:
        DataFrame: 중복이 제거된 데이터프레임
    """
    df = data.copy()
    duplicate_rows = df.duplicated()
    num_duplicates = duplicate_rows.sum() 
    print(f"중복된 행의 수: {num_duplicates}")

    if drop and num_duplicates > 0:
        df = df.drop_duplicates()
        print("중복된 행이 제거되었습니다.")

    return df

check_missing_values

check_missing_values(data)

데이터프레임에서 컬럼별 결측치 개수와 비율을 계산하여 데이터 프레임으로 반환하는 함수

Parameters:

Name Type Description Default
data DataFrame

결측치를 점검할 데이터프레임

required

Returns:

Name Type Description
DataFrame

컬럼별 결측치 개수와 비율이 포함된 데이터프레임

Source code in hossam/my_qtcheck.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
def check_missing_values(data):
    """
    데이터프레임에서 컬럼별 결측치 개수와 비율을 계산하여 데이터 프레임으로 반환하는 함수

    Args:
        data (DataFrame): 결측치를 점검할 데이터프레임

    Returns:
        DataFrame: 컬럼별 결측치 개수와 비율이 포함된 데이터프레임
    """
    na_count = data.isna().sum()
    na_ratio = (na_count / len(data)) * 100

    return DataFrame({
        'Missing Count': na_count,
        'Missing Ratio (%)': na_ratio
    })

categorical_summary

categorical_summary(
    data, columns=None, value_counts=True, save_path=None
)

데이터프레임의 범주형 컬럼에 대한 요약 통계를 반환하는 함수

Parameters:

Name Type Description Default
data DataFrame

범주형 컬럼의 요약 통계를 출력할 데이터프레임

required
columns list

요약 통계를 출력할 범주형 컬럼 리스트

None
value_counts bool

각 범주형 컬럼의 value_counts()를 출력할지 여부 (기본값: True)

True
save_path str

요약 통계 결과를 CSV 파일로 저장할 경로 (기본값: None, 저장하지 않음)

None

Returns:

Name Type Description
DataFrame

범주형 컬럼에 대한 요약 통계가 포함된 데이터프레임

Source code in hossam/my_qtcheck.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
def categorical_summary(data, columns=None, value_counts=True, save_path=None):
    """
    데이터프레임의 범주형 컬럼에 대한 요약 통계를 반환하는 함수

    Args:
        data (DataFrame): 범주형 컬럼의 요약 통계를 출력할 데이터프레임
        columns (list): 요약 통계를 출력할 범주형 컬럼 리스트
        value_counts (bool): 각 범주형 컬럼의 value_counts()를 출력할지 여부 (기본값: True)
        save_path (str): 요약 통계 결과를 CSV 파일로 저장할 경로 (기본값: None, 저장하지 않음)

    Returns:
        DataFrame: 범주형 컬럼에 대한 요약 통계가 포함된 데이터프레임
    """
    # columns가 비어있으면 데이터프레임에서 범주형 컬럼의 이름을 가져옴
    if not columns:
        columns = get_categorical_column_names(data)

    # 대상 컬럼으로 데이터프레임 생성
    df = data[columns].copy()

    # 명목형 변수의 기술 통계량 계산
    desc_df = df.describe(include="category")

    # 저장될 파일 경로가 전달된 경우 기술 통계량을 Excel 파일로 저장
    if save_path:
        desc_df.to_excel(save_path, sheet_name='Summary', index=True)

    # 각 범주형 컬럼의 value_counts()를 출력해야 한다면?
    if value_counts:
        for col in columns:
            cdf = DataFrame(data[col].value_counts())
            cdf.index.name = col
            cdf.sort_index(inplace=True)
            print(f"📊 컬럼 '{col}'의 value_counts():")
            display(cdf)

            # 저장될 파일 경로가 전달된 경우 value_counts 결과를 Excel 파일로 저장
            if save_path:
                # 기존 파일에 이어 쓰기를 수행하기 위해 ExcelWriter를 사용하여 시트별로 저장
                with ExcelWriter(save_path, mode='a') as excel_writer:
                    cdf.to_excel(excel_writer, sheet_name=col, index=True)

    return desc_df

numerical_summary

numerical_summary(data, columns=None, save_path=None)

데이터프레임의 숫자형 컬럼에 대한 요약 통계를 반환하는 함수

Parameters:

Name Type Description Default
data DataFrame

숫자형 컬럼의 요약 통계를 출력할 데이터프레임

required
columns list

요약 통계를 출력할 숫자형 컬럼 리스트

None
save_path str

요약 통계 결과를 CSV 파일로 저장할 경로 (기본값: None, 저장하지 않음)

None

Returns:

Name Type Description
DataFrame

숫자형 컬럼에 대한 요약 통계가 포함된 데이터프레임

Source code in hossam/my_qtcheck.py
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
def numerical_summary(data, columns=None, save_path=None):
    """
    데이터프레임의 숫자형 컬럼에 대한 요약 통계를 반환하는 함수

    Args:
        data (DataFrame): 숫자형 컬럼의 요약 통계를 출력할 데이터프레임
        columns (list): 요약 통계를 출력할 숫자형 컬럼 리스트
        save_path (str): 요약 통계 결과를 CSV 파일로 저장할 경로 (기본값: None, 저장하지 않음)

    Returns:
        DataFrame: 숫자형 컬럼에 대한 요약 통계가 포함된 데이터프레임
    """
    #-----------------------------------------------------
    # 1) columns가 비어있으면 데이터프레임에서 숫자형 컬럼의 이름을 가져옴
    #-----------------------------------------------------
    if not columns:
        columns = get_number_column_names(data)

    desc_df = data[columns].describe().T

    #-----------------------------------------------------
    # 2) 평균-중앙값의 상대 차이율을 계산하여 중심 수준 파악
    #-----------------------------------------------------
    # "평균-중앙값 상대 차이율 = |평균 - 중앙값| / 중앙값" 컬럼 추가
    desc_df['rel_diff'] = abs(desc_df['mean'] - desc_df['50%']) / desc_df['50%']

    # 상대 차이율 의미 컬럼 추가
    conditions = [desc_df['rel_diff'] < 0.1, desc_df['rel_diff'] < 0.5]
    choices = ['similar', 'diff']
    desc_df['rdiff_flag'] = np.select(conditions, choices, default='large_diff')

    #-----------------------------------------------------
    # 3) IQR, 이상치 경계값 계산
    #-----------------------------------------------------
    # iqr
    desc_df['iqr'] = desc_df['75%'] - desc_df['25%']

    # 상한 이상치 경계
    desc_df['upper_bound'] = desc_df['75%'] + 1.5 * desc_df['iqr']

    # 하한 이상치 경계
    desc_df['lower_bound'] = desc_df['25%'] - 1.5 * desc_df['iqr']

    #-----------------------------------------------------
    # 4) 명목형 변수를 제외한 데이터 프레임 생성
    #-----------------------------------------------------
    df = data[columns].copy()

    #-----------------------------------------------------
    # 5) 상한 이상치 탐지
    #-----------------------------------------------------
    # 상한 이상치 수
    desc_df['upper_outliers'] = ((df > desc_df['upper_bound'])).sum()

    # 상한 이상치 수 비율
    desc_df['upper_outliers_ratio'] = desc_df['upper_outliers'] / df.shape[0]

    #-----------------------------------------------------
    # 6) 하한 이상치 탐지
    #-----------------------------------------------------
    # 하한 이상치 수
    desc_df['lower_outliers'] = ((df < desc_df['lower_bound'])).sum()

    # 하한 이상치 수 비율
    desc_df['lower_outliers_ratio'] = desc_df['lower_outliers'] / df.shape[0]

    #-----------------------------------------------------
    # 7) 전체 이상치 집계
    #-----------------------------------------------------
    # 통합 이상치 수
    desc_df['outliers'] = desc_df['upper_outliers'] + desc_df['lower_outliers']

    # 통합 이상치 수 비율
    desc_df['outliers_ratio'] = desc_df['outliers'] / df.shape[0]

    #-----------------------------------------------------
    # 8) 왜도 점검
    #-----------------------------------------------------
    # 왜도 계산
    desc_df['skew'] = df.skew()

    # 왜도를 통한 분포 형태 해석
    conditions_skew = [(desc_df['skew'] < -0.5), (desc_df['skew'] > 0.5)]
    choices_skew = ['left tail', 'right tail']
    desc_df['skew_interpret'] = np.select(conditions_skew, choices_skew, default='symmetric')

    #-----------------------------------------------------
    # 9) 첨도 점검
    #-----------------------------------------------------
    # 첨도 계산
    desc_df['kurt'] = df.kurt()

    # 첨도를 통한 분포 형태 해석
    conditions_kurt = [(desc_df['kurt'] < 0), (desc_df['kurt'] > 0)]
    choices_kurt = ['platykurtic', 'leptokurtic']
    desc_df['kurt_interpret'] = np.select(conditions_kurt, choices_kurt, default='mesokurtic')

    #-----------------------------------------------------
    # 10) 로그 변환 필요성 판단 함수 정의 (inner function)
    #-----------------------------------------------------
    def judge_log_transform(skew, kurt):
        if skew >= 1:                        # 강한 우측 꼬리 분포
            return "log1p"
        elif skew > 0.5 and kurt > 0:       # 우측 꼬리 분포이면서 첨도가 높은 경우
            return "log1p"
        elif skew <= -1:                    # 강한 좌측 꼬리 분포
            return "reverse_log1p"
        elif skew < -0.5 and kurt > 0:      # 좌측 꼬리 분포이면서 첨도가 높은 경우
            return "reverse_log1p"
        else:                               # 대칭 분포
            return "none"

    #-----------------------------------------------------
    # 11) 로그 변환 필요성 판정
    #-----------------------------------------------------
    desc_df['log_need'] = desc_df.apply(lambda row: judge_log_transform( row['skew'], row['kurt']), axis=1)

    #-----------------------------------------------------
    # 12) 기술 통계량 표 저장
    #-----------------------------------------------------
    # 저장 경로 파라미터가 전달되었다면 기술 통계량 표를 Excel 파일로 저장
    if save_path:
        desc_df.to_excel(save_path, index=True)

    #-----------------------------------------------------
    # 13) 결과 리턴
    #-----------------------------------------------------
    return desc_df