hossam 0.4.4__py3-none-any.whl → 0.4.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hossam/__init__.py +2 -1
- hossam/hs_classroom.py +30 -30
- hossam/hs_gis.py +17 -18
- hossam/hs_plot.py +334 -347
- hossam/hs_prep.py +36 -31
- hossam/hs_stats.py +1360 -1250
- hossam/hs_timeserise.py +38 -39
- hossam/hs_util.py +202 -7
- {hossam-0.4.4.dist-info → hossam-0.4.6.dist-info}/METADATA +1 -1
- hossam-0.4.6.dist-info/RECORD +15 -0
- hossam/data_loader.py +0 -205
- hossam-0.4.4.dist-info/RECORD +0 -16
- {hossam-0.4.4.dist-info → hossam-0.4.6.dist-info}/WHEEL +0 -0
- {hossam-0.4.4.dist-info → hossam-0.4.6.dist-info}/licenses/LICENSE +0 -0
- {hossam-0.4.4.dist-info → hossam-0.4.6.dist-info}/top_level.txt +0 -0
hossam/hs_prep.py
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import joblib
|
|
6
6
|
import numpy as np
|
|
7
7
|
from itertools import combinations
|
|
8
|
+
from typing import Any
|
|
8
9
|
|
|
9
10
|
import pandas as pd
|
|
10
11
|
import jenkspy
|
|
@@ -19,7 +20,7 @@ from .hs_util import pretty_table
|
|
|
19
20
|
# 연속형 변수를 표준정규화(Z-score)로 변환한다
|
|
20
21
|
# ===================================================================
|
|
21
22
|
def standard_scaler(
|
|
22
|
-
data:
|
|
23
|
+
data: Any, yname: str | None = None, save_path: str | None = None, load_path: str | None = None
|
|
23
24
|
) -> DataFrame:
|
|
24
25
|
"""연속형 변수에 대해 Standard Scaling을 수행한다.
|
|
25
26
|
|
|
@@ -54,7 +55,7 @@ def standard_scaler(
|
|
|
54
55
|
sdata = scaler.transform(arr) if load_path else scaler.fit_transform(arr)
|
|
55
56
|
if save_path:
|
|
56
57
|
joblib.dump(value=scaler, filename=save_path)
|
|
57
|
-
return sdata
|
|
58
|
+
return sdata # type: ignore
|
|
58
59
|
|
|
59
60
|
df = data.copy()
|
|
60
61
|
|
|
@@ -90,7 +91,7 @@ def standard_scaler(
|
|
|
90
91
|
# 연속형 변수를 0부터 1 사이의 값으로 정규화한다
|
|
91
92
|
# ===================================================================
|
|
92
93
|
def minmax_scaler(
|
|
93
|
-
data:
|
|
94
|
+
data: Any, yname: str | None = None, save_path: str | None = None, load_path: str | None = None
|
|
94
95
|
) -> DataFrame:
|
|
95
96
|
"""연속형 변수에 대해 MinMax Scaling을 수행한다.
|
|
96
97
|
|
|
@@ -123,7 +124,7 @@ def minmax_scaler(
|
|
|
123
124
|
sdata = scaler.transform(arr) if load_path else scaler.fit_transform(arr)
|
|
124
125
|
if save_path:
|
|
125
126
|
joblib.dump(scaler, save_path)
|
|
126
|
-
return sdata
|
|
127
|
+
return sdata # type: ignore
|
|
127
128
|
|
|
128
129
|
df = data.copy()
|
|
129
130
|
|
|
@@ -158,7 +159,7 @@ def minmax_scaler(
|
|
|
158
159
|
# ===================================================================
|
|
159
160
|
# 지정된 컬럼들을 범주형 데이터로 설정한다
|
|
160
161
|
# ===================================================================
|
|
161
|
-
def set_category(data: DataFrame, *args: str, columns: list = None) -> DataFrame:
|
|
162
|
+
def set_category(data: DataFrame, *args: str, columns: list | None = None) -> DataFrame:
|
|
162
163
|
"""카테고리 데이터를 설정한다.
|
|
163
164
|
|
|
164
165
|
Args:
|
|
@@ -173,7 +174,7 @@ def set_category(data: DataFrame, *args: str, columns: list = None) -> DataFrame
|
|
|
173
174
|
if columns is not None:
|
|
174
175
|
if args:
|
|
175
176
|
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
176
|
-
args = columns
|
|
177
|
+
args = columns # type: ignore
|
|
177
178
|
|
|
178
179
|
df = data.copy()
|
|
179
180
|
|
|
@@ -226,7 +227,7 @@ def unmelt(
|
|
|
226
227
|
# ===================================================================
|
|
227
228
|
# 지정된 변수의 이상치 테이블로 반환한다
|
|
228
229
|
# ===================================================================
|
|
229
|
-
def outlier_table(data: DataFrame, *fields: str, columns: list = None) -> DataFrame:
|
|
230
|
+
def outlier_table(data: DataFrame, *fields: str, columns: list | None = None) -> DataFrame:
|
|
230
231
|
"""수치형 컬럼에 대한 사분위수 및 IQR 기반 이상치 경계를 계산한다.
|
|
231
232
|
|
|
232
233
|
전달된 `fields`가 없으면 데이터프레임의 모든 수치형 컬럼을 대상으로 한다.
|
|
@@ -246,7 +247,7 @@ def outlier_table(data: DataFrame, *fields: str, columns: list = None) -> DataFr
|
|
|
246
247
|
"""
|
|
247
248
|
# columns 인자가 있으면 args보다 우선한다.
|
|
248
249
|
if columns is not None:
|
|
249
|
-
if args:
|
|
250
|
+
if args: # type: ignore
|
|
250
251
|
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
251
252
|
args = columns
|
|
252
253
|
|
|
@@ -286,7 +287,7 @@ def outlier_table(data: DataFrame, *fields: str, columns: list = None) -> DataFr
|
|
|
286
287
|
# ===================================================================
|
|
287
288
|
# 이상치를 대체값(NaN, 0) 또는 중앙값으로 교체한다
|
|
288
289
|
# ===================================================================
|
|
289
|
-
def replace_outliner(data: DataFrame, method: str = "nan", *fields: str, columns: list = None) -> DataFrame:
|
|
290
|
+
def replace_outliner(data: DataFrame, method: str = "nan", *fields: str, columns: list | None = None) -> DataFrame:
|
|
290
291
|
"""이상치 경계값을 넘어가는 데이터를 경계값으로 대체한다.
|
|
291
292
|
|
|
292
293
|
Args:
|
|
@@ -305,7 +306,7 @@ def replace_outliner(data: DataFrame, method: str = "nan", *fields: str, columns
|
|
|
305
306
|
"""
|
|
306
307
|
# columns 인자가 있으면 args보다 우선한다.
|
|
307
308
|
if columns is not None:
|
|
308
|
-
if args:
|
|
309
|
+
if args: # type: ignore
|
|
309
310
|
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
310
311
|
args = columns
|
|
311
312
|
|
|
@@ -354,7 +355,7 @@ def replace_outliner(data: DataFrame, method: str = "nan", *fields: str, columns
|
|
|
354
355
|
# ===================================================================
|
|
355
356
|
# 중빈 이상치를 제거한 연처리된 데이터프레임을 반환한다
|
|
356
357
|
# ===================================================================
|
|
357
|
-
def drop_outliner(data: DataFrame, *fields: str, columns: list = None) -> DataFrame:
|
|
358
|
+
def drop_outliner(data: DataFrame, *fields: str, columns: list | None = None) -> DataFrame:
|
|
358
359
|
"""이상치를 결측치로 변환한 후 모두 삭제한다.
|
|
359
360
|
|
|
360
361
|
Args:
|
|
@@ -367,7 +368,7 @@ def drop_outliner(data: DataFrame, *fields: str, columns: list = None) -> DataFr
|
|
|
367
368
|
"""
|
|
368
369
|
# columns 인자가 있으면 args보다 우선한다.
|
|
369
370
|
if columns is not None:
|
|
370
|
-
if args:
|
|
371
|
+
if args: # type: ignore
|
|
371
372
|
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
372
373
|
args = columns
|
|
373
374
|
|
|
@@ -378,7 +379,7 @@ def drop_outliner(data: DataFrame, *fields: str, columns: list = None) -> DataFr
|
|
|
378
379
|
# ===================================================================
|
|
379
380
|
# 범주 변수를 더미 변수(One-Hot 인코딩)로 변환한다
|
|
380
381
|
# ===================================================================
|
|
381
|
-
def get_dummies(data: DataFrame, *args: str, columns: list = None, drop_first: bool = True, dtype: str = "int") -> DataFrame:
|
|
382
|
+
def get_dummies(data: DataFrame, *args: str, columns: list | None = None, drop_first: bool = True, dtype: str = "int") -> DataFrame:
|
|
382
383
|
"""명목형 변수를 더미 변수로 변환한다.
|
|
383
384
|
|
|
384
385
|
컬럼명을 지정하면 그 컬럼들만 더미 변수로 변환하고,
|
|
@@ -409,7 +410,7 @@ def get_dummies(data: DataFrame, *args: str, columns: list = None, drop_first: b
|
|
|
409
410
|
if columns is not None:
|
|
410
411
|
if args:
|
|
411
412
|
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
412
|
-
args = columns
|
|
413
|
+
args = columns # type: ignore
|
|
413
414
|
|
|
414
415
|
if not args:
|
|
415
416
|
# args가 없으면 숫자 타입이 아닌 모든 컬럼 자동 선택
|
|
@@ -417,13 +418,13 @@ def get_dummies(data: DataFrame, *args: str, columns: list = None, drop_first: b
|
|
|
417
418
|
for f in data.columns:
|
|
418
419
|
if not pd.api.types.is_numeric_dtype(data[f]):
|
|
419
420
|
cols_to_convert.append(f)
|
|
420
|
-
args = cols_to_convert
|
|
421
|
+
args = cols_to_convert # type: ignore
|
|
421
422
|
else:
|
|
422
423
|
# args가 있으면 그 컬럼들만 사용 (존재 여부 확인)
|
|
423
|
-
args = [c for c in args if c in data.columns]
|
|
424
|
+
args = [c for c in args if c in data.columns] # type: ignore
|
|
424
425
|
|
|
425
426
|
# pandas.get_dummies 사용 (재귀 문제 없음)
|
|
426
|
-
return pd.get_dummies(data, columns=args, drop_first=drop_first, dtype=dtype) if args else data.copy()
|
|
427
|
+
return pd.get_dummies(data, columns=args, drop_first=drop_first, dtype=dtype) if args else data.copy() # type: ignore
|
|
427
428
|
|
|
428
429
|
|
|
429
430
|
# ===================================================================
|
|
@@ -630,7 +631,7 @@ def bin_continuous(
|
|
|
630
631
|
if apply_labels:
|
|
631
632
|
# 숫자 인덱스 사용 (0, 1, 2, ...)
|
|
632
633
|
numeric_labels = list(range(len(edges) - 1))
|
|
633
|
-
df[new_col] = pd.cut(series, bins=edges, labels=numeric_labels, include_lowest=True, ordered=False)
|
|
634
|
+
df[new_col] = pd.cut(series, bins=edges, labels=numeric_labels, include_lowest=True, ordered=False) # type: ignore
|
|
634
635
|
else:
|
|
635
636
|
# 문자 레이블 적용
|
|
636
637
|
if labels is None:
|
|
@@ -645,9 +646,9 @@ def bin_continuous(
|
|
|
645
646
|
except:
|
|
646
647
|
pass
|
|
647
648
|
auto_labels.append(f"{left}~{right}")
|
|
648
|
-
df[new_col] = pd.cut(series, bins=edges, labels=auto_labels, include_lowest=True, ordered=False)
|
|
649
|
+
df[new_col] = pd.cut(series, bins=edges, labels=auto_labels, include_lowest=True, ordered=False) # type: ignore
|
|
649
650
|
else:
|
|
650
|
-
df[new_col] = pd.cut(series, bins=edges, labels=labels, include_lowest=True, ordered=False)
|
|
651
|
+
df[new_col] = pd.cut(series, bins=edges, labels=labels, include_lowest=True, ordered=False) # type: ignore
|
|
651
652
|
|
|
652
653
|
df[new_col] = df[new_col].astype("category")
|
|
653
654
|
return df
|
|
@@ -671,26 +672,24 @@ def bin_continuous(
|
|
|
671
672
|
n_bins = len(edges) - 1
|
|
672
673
|
if apply_labels:
|
|
673
674
|
numeric_labels = list(range(n_bins))
|
|
674
|
-
df[new_col] = pd.cut(series, bins=edges, labels=numeric_labels, include_lowest=True, ordered=False)
|
|
675
|
+
df[new_col] = pd.cut(series, bins=edges, labels=numeric_labels, include_lowest=True, ordered=False) # type: ignore
|
|
675
676
|
else:
|
|
676
677
|
if labels is None:
|
|
677
678
|
position_labels = [f"Q{i+1}" for i in range(n_bins)]
|
|
678
|
-
df[new_col] = pd.cut(
|
|
679
|
-
series, bins=edges, labels=position_labels, include_lowest=True, ordered=False
|
|
680
|
-
)
|
|
679
|
+
df[new_col] = pd.cut(series, bins=edges, labels=position_labels, include_lowest=True, ordered=False) # type: ignore
|
|
681
680
|
else:
|
|
682
|
-
df[new_col] = pd.cut(series, bins=edges, labels=labels, include_lowest=True, ordered=False)
|
|
681
|
+
df[new_col] = pd.cut(series, bins=edges, labels=labels, include_lowest=True, ordered=False) # type: ignore
|
|
683
682
|
df[new_col] = df[new_col].astype("category")
|
|
684
683
|
return df
|
|
685
684
|
|
|
686
685
|
# 자연 구간화 (Jenks) - 의존성 없으면 분위수로 폴백
|
|
687
686
|
if method_key in {"natural_breaks", "natural", "jenks"}:
|
|
688
687
|
k = bins if isinstance(bins, int) and bins > 1 else 5
|
|
689
|
-
series_nonnull = series.dropna()
|
|
688
|
+
series_nonnull = series.dropna() # type: ignore
|
|
690
689
|
k = min(k, max(2, series_nonnull.nunique()))
|
|
691
690
|
edges = None
|
|
692
691
|
try:
|
|
693
|
-
edges = jenkspy.jenks_breaks(series_nonnull.to_list(), nb_class=k)
|
|
692
|
+
edges = jenkspy.jenks_breaks(series_nonnull.to_list(), nb_class=k) # type: ignore
|
|
694
693
|
edges[0] = -np.inf
|
|
695
694
|
edges[-1] = np.inf
|
|
696
695
|
except Exception:
|
|
@@ -730,7 +729,7 @@ def bin_continuous(
|
|
|
730
729
|
if apply_labels:
|
|
731
730
|
# 숫자 인덱스 사용
|
|
732
731
|
numeric_labels = list(range(len(cut_edges) - 1))
|
|
733
|
-
df[new_col] = pd.cut(series, bins=cut_edges, labels=numeric_labels, include_lowest=True, ordered=False)
|
|
732
|
+
df[new_col] = pd.cut(series, bins=cut_edges, labels=numeric_labels, include_lowest=True, ordered=False) # type: ignore
|
|
734
733
|
else:
|
|
735
734
|
if labels is None:
|
|
736
735
|
auto_labels = []
|
|
@@ -744,9 +743,9 @@ def bin_continuous(
|
|
|
744
743
|
except:
|
|
745
744
|
pass
|
|
746
745
|
auto_labels.append(f"{left}~{right}")
|
|
747
|
-
df[new_col] = pd.cut(series, bins=cut_edges, labels=auto_labels, include_lowest=True, ordered=False)
|
|
746
|
+
df[new_col] = pd.cut(series, bins=cut_edges, labels=auto_labels, include_lowest=True, ordered=False) # type: ignore
|
|
748
747
|
else:
|
|
749
|
-
df[new_col] = pd.cut(series, bins=cut_edges, labels=labels, include_lowest=True, ordered=False)
|
|
748
|
+
df[new_col] = pd.cut(series, bins=cut_edges, labels=labels, include_lowest=True, ordered=False) # type: ignore
|
|
750
749
|
df[new_col] = df[new_col].astype("category")
|
|
751
750
|
return df
|
|
752
751
|
|
|
@@ -765,7 +764,7 @@ def bin_continuous(
|
|
|
765
764
|
# ===================================================================
|
|
766
765
|
# 지정된 변수에 로그 먼저 변환을 적용한다
|
|
767
766
|
# ===================================================================
|
|
768
|
-
def log_transform(data: DataFrame, *fields: str) -> DataFrame:
|
|
767
|
+
def log_transform(data: DataFrame, *fields: str, columns: list | None = None) -> DataFrame:
|
|
769
768
|
"""수치형 변수에 대해 로그 변환을 수행한다.
|
|
770
769
|
|
|
771
770
|
자연로그(ln)를 사용하여 변환하며, 0 또는 음수 값이 있을 경우
|
|
@@ -774,6 +773,7 @@ def log_transform(data: DataFrame, *fields: str) -> DataFrame:
|
|
|
774
773
|
Args:
|
|
775
774
|
data (DataFrame): 변환할 데이터프레임.
|
|
776
775
|
*fields (str): 변환할 컬럼명 목록. 지정하지 않으면 모든 수치형 컬럼을 처리.
|
|
776
|
+
columns (list, optional): 변환할 컬럼명 목록. fields와 중복 사용 불가.
|
|
777
777
|
|
|
778
778
|
Returns:
|
|
779
779
|
DataFrame: 로그 변환된 데이터프레임.
|
|
@@ -800,6 +800,11 @@ def log_transform(data: DataFrame, *fields: str) -> DataFrame:
|
|
|
800
800
|
"""
|
|
801
801
|
df = data.copy()
|
|
802
802
|
|
|
803
|
+
if columns is not None:
|
|
804
|
+
if fields:
|
|
805
|
+
raise ValueError("fields와 columns 인자는 중복 사용할 수 없습니다.")
|
|
806
|
+
fields = columns # type: ignore
|
|
807
|
+
|
|
803
808
|
# 대상 컬럼 결정
|
|
804
809
|
if not fields:
|
|
805
810
|
# 모든 수치형 컬럼 선택
|