hossam 0.4.3__py3-none-any.whl → 0.4.5__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/data_loader.py +7 -9
- hossam/hs_gis.py +17 -18
- hossam/hs_plot.py +220 -220
- hossam/hs_prep.py +56 -25
- hossam/hs_stats.py +199 -67
- hossam/hs_util.py +4 -6
- {hossam-0.4.3.dist-info → hossam-0.4.5.dist-info}/METADATA +1 -1
- hossam-0.4.5.dist-info/RECORD +16 -0
- hossam-0.4.3.dist-info/RECORD +0 -16
- {hossam-0.4.3.dist-info → hossam-0.4.5.dist-info}/WHEEL +0 -0
- {hossam-0.4.3.dist-info → hossam-0.4.5.dist-info}/licenses/LICENSE +0 -0
- {hossam-0.4.3.dist-info → hossam-0.4.5.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,16 +159,23 @@ def minmax_scaler(
|
|
|
158
159
|
# ===================================================================
|
|
159
160
|
# 지정된 컬럼들을 범주형 데이터로 설정한다
|
|
160
161
|
# ===================================================================
|
|
161
|
-
def set_category(data: DataFrame, *args: str) -> DataFrame:
|
|
162
|
+
def set_category(data: DataFrame, *args: str, columns: list | None = None) -> DataFrame:
|
|
162
163
|
"""카테고리 데이터를 설정한다.
|
|
163
164
|
|
|
164
165
|
Args:
|
|
165
166
|
data (DataFrame): 데이터프레임 객체
|
|
166
167
|
*args (str): 컬럼명 목록
|
|
168
|
+
columns (list, optional): 변환할 컬럼명 목록. args와 중복 사용 불가.
|
|
167
169
|
|
|
168
170
|
Returns:
|
|
169
171
|
DataFrame: 카테고리 설정된 데이터프레임
|
|
170
172
|
"""
|
|
173
|
+
# columns 인자가 있으면 args보다 우선한다.
|
|
174
|
+
if columns is not None:
|
|
175
|
+
if args:
|
|
176
|
+
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
177
|
+
args = columns # type: ignore
|
|
178
|
+
|
|
171
179
|
df = data.copy()
|
|
172
180
|
|
|
173
181
|
for k in args:
|
|
@@ -219,7 +227,7 @@ def unmelt(
|
|
|
219
227
|
# ===================================================================
|
|
220
228
|
# 지정된 변수의 이상치 테이블로 반환한다
|
|
221
229
|
# ===================================================================
|
|
222
|
-
def outlier_table(data: DataFrame, *fields: str) -> DataFrame:
|
|
230
|
+
def outlier_table(data: DataFrame, *fields: str, columns: list | None = None) -> DataFrame:
|
|
223
231
|
"""수치형 컬럼에 대한 사분위수 및 IQR 기반 이상치 경계를 계산한다.
|
|
224
232
|
|
|
225
233
|
전달된 `fields`가 없으면 데이터프레임의 모든 수치형 컬럼을 대상으로 한다.
|
|
@@ -228,6 +236,7 @@ def outlier_table(data: DataFrame, *fields: str) -> DataFrame:
|
|
|
228
236
|
Args:
|
|
229
237
|
data (DataFrame): 분석할 데이터프레임.
|
|
230
238
|
*fields (str): 대상 컬럼명(들). 생략 시 모든 수치형 컬럼 대상.
|
|
239
|
+
columns (list, optional): 변환할 컬럼명 목록. args와 중복 사용 불가.
|
|
231
240
|
|
|
232
241
|
Returns:
|
|
233
242
|
DataFrame: Q1, Q2(중앙값), Q3, IQR, 하한, 상한을 포함한 통계표.
|
|
@@ -236,6 +245,11 @@ def outlier_table(data: DataFrame, *fields: str) -> DataFrame:
|
|
|
236
245
|
from hossam import *
|
|
237
246
|
hs_prep.outlier_table(df, "value")
|
|
238
247
|
"""
|
|
248
|
+
# columns 인자가 있으면 args보다 우선한다.
|
|
249
|
+
if columns is not None:
|
|
250
|
+
if args: # type: ignore
|
|
251
|
+
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
252
|
+
args = columns
|
|
239
253
|
|
|
240
254
|
target_fields = list(fields) if fields else list(data.select_dtypes(include=[np.number]).columns)
|
|
241
255
|
result = []
|
|
@@ -273,7 +287,7 @@ def outlier_table(data: DataFrame, *fields: str) -> DataFrame:
|
|
|
273
287
|
# ===================================================================
|
|
274
288
|
# 이상치를 대체값(NaN, 0) 또는 중앙값으로 교체한다
|
|
275
289
|
# ===================================================================
|
|
276
|
-
def replace_outliner(data: DataFrame, method: str = "nan", *fields: str) -> DataFrame:
|
|
290
|
+
def replace_outliner(data: DataFrame, method: str = "nan", *fields: str, columns: list | None = None) -> DataFrame:
|
|
277
291
|
"""이상치 경계값을 넘어가는 데이터를 경계값으로 대체한다.
|
|
278
292
|
|
|
279
293
|
Args:
|
|
@@ -285,10 +299,16 @@ def replace_outliner(data: DataFrame, method: str = "nan", *fields: str) -> Data
|
|
|
285
299
|
- most: 최빈값 대체
|
|
286
300
|
- median: 중앙값 대체
|
|
287
301
|
*fields (str): 컬럼명 목록
|
|
302
|
+
columns (list, optional): 변환할 컬럼명 목록. args와 중복 사용 불가.
|
|
288
303
|
|
|
289
304
|
Returns:
|
|
290
305
|
DataFrame: 이상치가 경계값으로 대체된 데이터 프레임
|
|
291
306
|
"""
|
|
307
|
+
# columns 인자가 있으면 args보다 우선한다.
|
|
308
|
+
if columns is not None:
|
|
309
|
+
if args: # type: ignore
|
|
310
|
+
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
311
|
+
args = columns
|
|
292
312
|
|
|
293
313
|
# 원본 데이터 프레임 복사
|
|
294
314
|
df = data.copy()
|
|
@@ -335,16 +355,22 @@ def replace_outliner(data: DataFrame, method: str = "nan", *fields: str) -> Data
|
|
|
335
355
|
# ===================================================================
|
|
336
356
|
# 중빈 이상치를 제거한 연처리된 데이터프레임을 반환한다
|
|
337
357
|
# ===================================================================
|
|
338
|
-
def drop_outliner(data: DataFrame, *fields: str) -> DataFrame:
|
|
358
|
+
def drop_outliner(data: DataFrame, *fields: str, columns: list | None = None) -> DataFrame:
|
|
339
359
|
"""이상치를 결측치로 변환한 후 모두 삭제한다.
|
|
340
360
|
|
|
341
361
|
Args:
|
|
342
362
|
data (DataFrame): 데이터프레임
|
|
343
363
|
*fields (str): 컬럼명 목록
|
|
364
|
+
columns (list, optional): 변환할 컬럼명 목록. args와 중복 사용 불가.
|
|
344
365
|
|
|
345
366
|
Returns:
|
|
346
367
|
DataFrame: 이상치가 삭제된 데이터프레임
|
|
347
368
|
"""
|
|
369
|
+
# columns 인자가 있으면 args보다 우선한다.
|
|
370
|
+
if columns is not None:
|
|
371
|
+
if args: # type: ignore
|
|
372
|
+
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
373
|
+
args = columns
|
|
348
374
|
|
|
349
375
|
df = replace_outliner(data, "nan", *fields)
|
|
350
376
|
return df.dropna()
|
|
@@ -353,7 +379,7 @@ def drop_outliner(data: DataFrame, *fields: str) -> DataFrame:
|
|
|
353
379
|
# ===================================================================
|
|
354
380
|
# 범주 변수를 더미 변수(One-Hot 인코딩)로 변환한다
|
|
355
381
|
# ===================================================================
|
|
356
|
-
def get_dummies(data: DataFrame, *args: str, drop_first=True, dtype="int") -> DataFrame:
|
|
382
|
+
def get_dummies(data: DataFrame, *args: str, columns: list | None = None, drop_first: bool = True, dtype: str = "int") -> DataFrame:
|
|
357
383
|
"""명목형 변수를 더미 변수로 변환한다.
|
|
358
384
|
|
|
359
385
|
컬럼명을 지정하면 그 컬럼들만 더미 변수로 변환하고,
|
|
@@ -362,6 +388,7 @@ def get_dummies(data: DataFrame, *args: str, drop_first=True, dtype="int") -> Da
|
|
|
362
388
|
Args:
|
|
363
389
|
data (DataFrame): 데이터프레임
|
|
364
390
|
*args (str): 변환할 컬럼명 목록. 지정하지 않으면 숫자형이 아닌 모든 컬럼 자동 선택.
|
|
391
|
+
columns (list, optional): 변환할 컬럼명 목록. args와 중복 사용 불가.
|
|
365
392
|
drop_first (bool, optional): 첫 번째 더미 변수 제거 여부. 기본값 True.
|
|
366
393
|
dtype (str, optional): 더미 변수 데이터 타입. 기본값 "int".
|
|
367
394
|
|
|
@@ -379,19 +406,25 @@ def get_dummies(data: DataFrame, *args: str, drop_first=True, dtype="int") -> Da
|
|
|
379
406
|
result = hs_prep.get_dummies(df, 'col1', drop_first=False, dtype='bool')
|
|
380
407
|
```
|
|
381
408
|
"""
|
|
409
|
+
# columns 인자가 있으면 args보다 우선한다.
|
|
410
|
+
if columns is not None:
|
|
411
|
+
if args:
|
|
412
|
+
raise ValueError("args와 columns 인자는 중복 사용할 수 없습니다.")
|
|
413
|
+
args = columns # type: ignore
|
|
414
|
+
|
|
382
415
|
if not args:
|
|
383
416
|
# args가 없으면 숫자 타입이 아닌 모든 컬럼 자동 선택
|
|
384
417
|
cols_to_convert = []
|
|
385
418
|
for f in data.columns:
|
|
386
419
|
if not pd.api.types.is_numeric_dtype(data[f]):
|
|
387
420
|
cols_to_convert.append(f)
|
|
388
|
-
args = cols_to_convert
|
|
421
|
+
args = cols_to_convert # type: ignore
|
|
389
422
|
else:
|
|
390
423
|
# args가 있으면 그 컬럼들만 사용 (존재 여부 확인)
|
|
391
|
-
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
|
|
392
425
|
|
|
393
426
|
# pandas.get_dummies 사용 (재귀 문제 없음)
|
|
394
|
-
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
|
|
395
428
|
|
|
396
429
|
|
|
397
430
|
# ===================================================================
|
|
@@ -598,7 +631,7 @@ def bin_continuous(
|
|
|
598
631
|
if apply_labels:
|
|
599
632
|
# 숫자 인덱스 사용 (0, 1, 2, ...)
|
|
600
633
|
numeric_labels = list(range(len(edges) - 1))
|
|
601
|
-
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
|
|
602
635
|
else:
|
|
603
636
|
# 문자 레이블 적용
|
|
604
637
|
if labels is None:
|
|
@@ -613,9 +646,9 @@ def bin_continuous(
|
|
|
613
646
|
except:
|
|
614
647
|
pass
|
|
615
648
|
auto_labels.append(f"{left}~{right}")
|
|
616
|
-
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
|
|
617
650
|
else:
|
|
618
|
-
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
|
|
619
652
|
|
|
620
653
|
df[new_col] = df[new_col].astype("category")
|
|
621
654
|
return df
|
|
@@ -639,26 +672,24 @@ def bin_continuous(
|
|
|
639
672
|
n_bins = len(edges) - 1
|
|
640
673
|
if apply_labels:
|
|
641
674
|
numeric_labels = list(range(n_bins))
|
|
642
|
-
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
|
|
643
676
|
else:
|
|
644
677
|
if labels is None:
|
|
645
678
|
position_labels = [f"Q{i+1}" for i in range(n_bins)]
|
|
646
|
-
df[new_col] = pd.cut(
|
|
647
|
-
series, bins=edges, labels=position_labels, include_lowest=True, ordered=False
|
|
648
|
-
)
|
|
679
|
+
df[new_col] = pd.cut(series, bins=edges, labels=position_labels, include_lowest=True, ordered=False) # type: ignore
|
|
649
680
|
else:
|
|
650
|
-
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
|
|
651
682
|
df[new_col] = df[new_col].astype("category")
|
|
652
683
|
return df
|
|
653
684
|
|
|
654
685
|
# 자연 구간화 (Jenks) - 의존성 없으면 분위수로 폴백
|
|
655
686
|
if method_key in {"natural_breaks", "natural", "jenks"}:
|
|
656
687
|
k = bins if isinstance(bins, int) and bins > 1 else 5
|
|
657
|
-
series_nonnull = series.dropna()
|
|
688
|
+
series_nonnull = series.dropna() # type: ignore
|
|
658
689
|
k = min(k, max(2, series_nonnull.nunique()))
|
|
659
690
|
edges = None
|
|
660
691
|
try:
|
|
661
|
-
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
|
|
662
693
|
edges[0] = -np.inf
|
|
663
694
|
edges[-1] = np.inf
|
|
664
695
|
except Exception:
|
|
@@ -698,7 +729,7 @@ def bin_continuous(
|
|
|
698
729
|
if apply_labels:
|
|
699
730
|
# 숫자 인덱스 사용
|
|
700
731
|
numeric_labels = list(range(len(cut_edges) - 1))
|
|
701
|
-
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
|
|
702
733
|
else:
|
|
703
734
|
if labels is None:
|
|
704
735
|
auto_labels = []
|
|
@@ -712,9 +743,9 @@ def bin_continuous(
|
|
|
712
743
|
except:
|
|
713
744
|
pass
|
|
714
745
|
auto_labels.append(f"{left}~{right}")
|
|
715
|
-
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
|
|
716
747
|
else:
|
|
717
|
-
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
|
|
718
749
|
df[new_col] = df[new_col].astype("category")
|
|
719
750
|
return df
|
|
720
751
|
|