hossam 0.3.15__py3-none-any.whl → 0.3.17__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 +15 -11
- hossam/hs_plot.py +141 -14
- hossam/hs_prep.py +316 -34
- hossam/hs_stats.py +300 -12
- hossam/mcp/__init__.py +12 -0
- hossam/mcp/hs_classroom.py +22 -0
- hossam/mcp/hs_gis.py +30 -0
- hossam/mcp/hs_plot.py +53 -0
- hossam/mcp/hs_prep.py +61 -0
- hossam/mcp/hs_stats.py +25 -0
- hossam/mcp/hs_timeserise.py +22 -0
- hossam/mcp/hs_util.py +30 -0
- hossam/mcp/loader.py +29 -0
- hossam/mcp/server.py +675 -0
- hossam-0.3.17.dist-info/METADATA +205 -0
- hossam-0.3.17.dist-info/RECORD +27 -0
- hossam-0.3.17.dist-info/entry_points.txt +2 -0
- hossam-0.3.15.dist-info/METADATA +0 -636
- hossam-0.3.15.dist-info/RECORD +0 -16
- {hossam-0.3.15.dist-info → hossam-0.3.17.dist-info}/WHEEL +0 -0
- {hossam-0.3.15.dist-info → hossam-0.3.17.dist-info}/licenses/LICENSE +0 -0
- {hossam-0.3.15.dist-info → hossam-0.3.17.dist-info}/top_level.txt +0 -0
hossam/__init__.py
CHANGED
|
@@ -5,6 +5,7 @@ from matplotlib import font_manager as fm
|
|
|
5
5
|
from importlib.resources import files, as_file
|
|
6
6
|
from importlib.metadata import version
|
|
7
7
|
from types import SimpleNamespace
|
|
8
|
+
import sys
|
|
8
9
|
import warnings
|
|
9
10
|
|
|
10
11
|
try:
|
|
@@ -15,14 +16,14 @@ except Exception:
|
|
|
15
16
|
|
|
16
17
|
hs_fig = SimpleNamespace(
|
|
17
18
|
dpi=200,
|
|
18
|
-
width=
|
|
19
|
-
height=
|
|
20
|
-
font_size=
|
|
19
|
+
width=800,
|
|
20
|
+
height=480,
|
|
21
|
+
font_size=9.5,
|
|
21
22
|
font_weight="light",
|
|
22
|
-
frame_width=0.
|
|
23
|
-
line_width=1,
|
|
23
|
+
frame_width=0.5,
|
|
24
|
+
line_width=1.5,
|
|
24
25
|
grid_alpha=0.3,
|
|
25
|
-
grid_width=0.
|
|
26
|
+
grid_width=0.5,
|
|
26
27
|
fill_alpha=0.3
|
|
27
28
|
)
|
|
28
29
|
|
|
@@ -56,9 +57,10 @@ def _init_korean_font():
|
|
|
56
57
|
"pdf.fonttype": 42,
|
|
57
58
|
"ps.fonttype": 42,
|
|
58
59
|
})
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
if sys.stdout.isatty():
|
|
61
|
+
print(
|
|
62
|
+
"\n✅ 시각화를 위한 한글 글꼴(NotoSansKR-Regular)이 자동 적용되었습니다."
|
|
63
|
+
)
|
|
62
64
|
return
|
|
63
65
|
except Exception as e:
|
|
64
66
|
warnings.warn(f"\n한글 폰트 초기화: 패키지 폰트 사용 실패 ({e}).")
|
|
@@ -76,8 +78,10 @@ def _init():
|
|
|
76
78
|
f"🔖 Version: {__version__}",
|
|
77
79
|
]
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
# MCP/stdio 환경에서는 배너를 출력하지 않음 (stdout TTY일 때만 출력)
|
|
82
|
+
if sys.stdout.isatty():
|
|
83
|
+
for msg in messages:
|
|
84
|
+
print(f"{msg}")
|
|
81
85
|
|
|
82
86
|
_init_korean_font()
|
|
83
87
|
|
hossam/hs_plot.py
CHANGED
|
@@ -56,6 +56,9 @@ def get_default_ax(width: int = hs_fig.width, height: int = hs_fig.height, rows:
|
|
|
56
56
|
rows (int): 서브플롯 행 개수.
|
|
57
57
|
cols (int): 서브플롯 열 개수.
|
|
58
58
|
dpi (int): 해상도(DPI).
|
|
59
|
+
flatten (bool): Axes 배열을 1차원 리스트로 평탄화할지 여부.
|
|
60
|
+
ws (int|None): 서브플롯 가로 간격(`wspace`). rows/cols가 1보다 클 때만 적용.
|
|
61
|
+
hs (int|None): 서브플롯 세로 간격(`hspace`). rows/cols가 1보다 클 때만 적용.
|
|
59
62
|
|
|
60
63
|
Returns:
|
|
61
64
|
tuple[Figure, Axes]: 생성된 matplotlib Figure와 Axes 객체.
|
|
@@ -100,7 +103,7 @@ def finalize_plot(ax: Axes, callback: any = None, outparams: bool = False, save_
|
|
|
100
103
|
callback (Callable|None): 추가 설정을 위한 사용자 콜백.
|
|
101
104
|
outparams (bool): 내부에서 생성한 Figure인 경우 True.
|
|
102
105
|
save_path (str|None): 이미지 저장 경로. None이 아니면 해당 경로로 저장.
|
|
103
|
-
grid (bool): 그리드 표시 여부.
|
|
106
|
+
grid (bool): 그리드 표시 여부. 기본값은 True입니다.
|
|
104
107
|
|
|
105
108
|
Returns:
|
|
106
109
|
None
|
|
@@ -166,6 +169,7 @@ def lineplot(
|
|
|
166
169
|
height (int): 캔버스 세로 픽셀.
|
|
167
170
|
linewidth (float): 선 굵기.
|
|
168
171
|
dpi (int): 해상도.
|
|
172
|
+
save_path (str|None): 이미지 저장 경로. None이면 화면에 표시.
|
|
169
173
|
callback (Callable|None): Axes 후처리 콜백.
|
|
170
174
|
ax (Axes|None): 외부에서 전달한 Axes.
|
|
171
175
|
**params: seaborn lineplot 추가 인자.
|
|
@@ -230,6 +234,7 @@ def boxplot(
|
|
|
230
234
|
height (int): 캔버스 세로 픽셀.
|
|
231
235
|
linewidth (float): 선 굵기.
|
|
232
236
|
dpi (int): 그림 크기 및 해상도.
|
|
237
|
+
save_path (str|None): 이미지 저장 경로. None이면 화면에 표시.
|
|
233
238
|
callback (Callable|None): Axes 후처리 콜백.
|
|
234
239
|
ax (Axes|None): 외부에서 전달한 Axes.
|
|
235
240
|
**params: seaborn boxplot 추가 인자.
|
|
@@ -1847,6 +1852,7 @@ def distribution_by_class(
|
|
|
1847
1852
|
linewidth=linewidth,
|
|
1848
1853
|
dpi=dpi,
|
|
1849
1854
|
callback=callback,
|
|
1855
|
+
save_path=save_path
|
|
1850
1856
|
)
|
|
1851
1857
|
elif type == "hist":
|
|
1852
1858
|
histplot(
|
|
@@ -1861,6 +1867,7 @@ def distribution_by_class(
|
|
|
1861
1867
|
linewidth=linewidth,
|
|
1862
1868
|
dpi=dpi,
|
|
1863
1869
|
callback=callback,
|
|
1870
|
+
save_path=save_path
|
|
1864
1871
|
)
|
|
1865
1872
|
elif type == "histkde":
|
|
1866
1873
|
histplot(
|
|
@@ -1875,6 +1882,7 @@ def distribution_by_class(
|
|
|
1875
1882
|
linewidth=linewidth,
|
|
1876
1883
|
dpi=dpi,
|
|
1877
1884
|
callback=callback,
|
|
1885
|
+
save_path=save_path
|
|
1878
1886
|
)
|
|
1879
1887
|
|
|
1880
1888
|
|
|
@@ -1892,6 +1900,7 @@ def scatter_by_class(
|
|
|
1892
1900
|
height: int = hs_fig.height,
|
|
1893
1901
|
linewidth: float = hs_fig.line_width,
|
|
1894
1902
|
dpi: int = hs_fig.dpi,
|
|
1903
|
+
save_path: str = None,
|
|
1895
1904
|
callback: any = None,
|
|
1896
1905
|
) -> None:
|
|
1897
1906
|
"""종속변수(y)와 각 연속형 독립변수(x) 간 산점도/볼록껍질을 그린다.
|
|
@@ -1939,10 +1948,14 @@ def scatter_by_class(
|
|
|
1939
1948
|
|
|
1940
1949
|
if outline:
|
|
1941
1950
|
for v in group:
|
|
1942
|
-
convex_hull(data, v[0], v[1], hue, palette,
|
|
1951
|
+
convex_hull(data=data, xname=v[0], yname=v[1], hue=hue, palette=palette,
|
|
1952
|
+
width=width, height=height, linewidth=linewidth, dpi=dpi, callback=callback,
|
|
1953
|
+
save_path=save_path)
|
|
1943
1954
|
else:
|
|
1944
1955
|
for v in group:
|
|
1945
|
-
scatterplot(data, v[0], v[1], hue, palette,
|
|
1956
|
+
scatterplot(data=data, xname=v[0], yname=v[1], hue=hue, palette=palette,
|
|
1957
|
+
width=width, height=height, linewidth=linewidth, dpi=dpi, callback=callback,
|
|
1958
|
+
save_path=save_path)
|
|
1946
1959
|
|
|
1947
1960
|
|
|
1948
1961
|
# ===================================================================
|
|
@@ -1951,7 +1964,7 @@ def scatter_by_class(
|
|
|
1951
1964
|
def categorical_target_distribution(
|
|
1952
1965
|
data: DataFrame,
|
|
1953
1966
|
yname: str,
|
|
1954
|
-
|
|
1967
|
+
hue: list | str | None = None,
|
|
1955
1968
|
kind: str = "box",
|
|
1956
1969
|
kde_fill: bool = True,
|
|
1957
1970
|
palette: str | None = None,
|
|
@@ -1960,6 +1973,7 @@ def categorical_target_distribution(
|
|
|
1960
1973
|
linewidth: float = hs_fig.line_width,
|
|
1961
1974
|
dpi: int = hs_fig.dpi,
|
|
1962
1975
|
cols: int = 2,
|
|
1976
|
+
save_path: str = None,
|
|
1963
1977
|
callback: any = None,
|
|
1964
1978
|
) -> None:
|
|
1965
1979
|
"""명목형 변수별로 종속변수 분포 차이를 시각화한다.
|
|
@@ -1967,7 +1981,7 @@ def categorical_target_distribution(
|
|
|
1967
1981
|
Args:
|
|
1968
1982
|
data (DataFrame): 시각화할 데이터.
|
|
1969
1983
|
yname (str): 종속변수 컬럼명(연속형 추천).
|
|
1970
|
-
|
|
1984
|
+
hue (list|str|None): 명목형 독립변수 목록. None이면 자동 탐지.
|
|
1971
1985
|
kind (str): 'box', 'violin', 'kde'.
|
|
1972
1986
|
kde_fill (bool): kind='kde'일 때 영역 채우기 여부.
|
|
1973
1987
|
palette (str|None): 팔레트 이름.
|
|
@@ -1983,13 +1997,13 @@ def categorical_target_distribution(
|
|
|
1983
1997
|
"""
|
|
1984
1998
|
|
|
1985
1999
|
# 명목형 컬럼 후보: object, category, bool
|
|
1986
|
-
if
|
|
2000
|
+
if hue is None:
|
|
1987
2001
|
cat_cols = data.select_dtypes(include=["object", "category", "bool", "boolean"]).columns
|
|
1988
2002
|
target_cols = [c for c in cat_cols if c != yname]
|
|
1989
|
-
elif isinstance(
|
|
1990
|
-
target_cols = [
|
|
2003
|
+
elif isinstance(hue, str):
|
|
2004
|
+
target_cols = [hue]
|
|
1991
2005
|
else:
|
|
1992
|
-
target_cols = list(
|
|
2006
|
+
target_cols = list(hue)
|
|
1993
2007
|
|
|
1994
2008
|
if len(target_cols) == 0:
|
|
1995
2009
|
return
|
|
@@ -2030,7 +2044,7 @@ def categorical_target_distribution(
|
|
|
2030
2044
|
|
|
2031
2045
|
|
|
2032
2046
|
# ===================================================================
|
|
2033
|
-
#
|
|
2047
|
+
# ROC 커브를 시각화 한다.
|
|
2034
2048
|
# ===================================================================
|
|
2035
2049
|
def roc_curve_plot(
|
|
2036
2050
|
fit,
|
|
@@ -2100,14 +2114,13 @@ def roc_curve_plot(
|
|
|
2100
2114
|
|
|
2101
2115
|
|
|
2102
2116
|
# ===================================================================
|
|
2103
|
-
#
|
|
2117
|
+
# 혼동행렬 시각화
|
|
2104
2118
|
# ===================================================================
|
|
2105
2119
|
def confusion_matrix_plot(
|
|
2106
2120
|
fit,
|
|
2107
2121
|
threshold: float = 0.5,
|
|
2108
2122
|
width: int = hs_fig.width,
|
|
2109
2123
|
height: int = hs_fig.height,
|
|
2110
|
-
linewidth: float = hs_fig.line_width,
|
|
2111
2124
|
dpi: int = hs_fig.dpi,
|
|
2112
2125
|
save_path: str = None,
|
|
2113
2126
|
callback: any = None,
|
|
@@ -2120,7 +2133,6 @@ def confusion_matrix_plot(
|
|
|
2120
2133
|
threshold (float): 예측 확률을 이진 분류로 변환할 임계값. 기본값 0.5.
|
|
2121
2134
|
width (int): 캔버스 가로 픽셀.
|
|
2122
2135
|
height (int): 캔버스 세로 픽셀.
|
|
2123
|
-
linewidth (float): 선 굵기 (현재 사용되지 않음).
|
|
2124
2136
|
dpi (int): 해상도.
|
|
2125
2137
|
callback (Callable|None): Axes 후처리 콜백.
|
|
2126
2138
|
ax (Axes|None): 외부에서 전달한 Axes. None이면 새로 생성.
|
|
@@ -2152,7 +2164,7 @@ def confusion_matrix_plot(
|
|
|
2152
2164
|
|
|
2153
2165
|
|
|
2154
2166
|
# ===================================================================
|
|
2155
|
-
#
|
|
2167
|
+
# 레이더 차트(방사형 차트)
|
|
2156
2168
|
# ===================================================================
|
|
2157
2169
|
def radarplot(
|
|
2158
2170
|
df: DataFrame,
|
|
@@ -2279,3 +2291,118 @@ def radarplot(
|
|
|
2279
2291
|
ax.set_title('Radar Chart', pad=20)
|
|
2280
2292
|
|
|
2281
2293
|
finalize_plot(ax, callback, outparams, save_path)
|
|
2294
|
+
|
|
2295
|
+
|
|
2296
|
+
# ===================================================================
|
|
2297
|
+
# 연속형 데이터 분포 시각화 (KDE + Boxplot)
|
|
2298
|
+
# ===================================================================
|
|
2299
|
+
def distribution_plot(
|
|
2300
|
+
data: DataFrame,
|
|
2301
|
+
column: str,
|
|
2302
|
+
clevel: float = 0.95,
|
|
2303
|
+
orient: str = "h",
|
|
2304
|
+
hue: str | None = None,
|
|
2305
|
+
kind: str = "boxplot",
|
|
2306
|
+
width: int = hs_fig.width,
|
|
2307
|
+
height: int = hs_fig.height,
|
|
2308
|
+
linewidth: float = hs_fig.line_width,
|
|
2309
|
+
dpi: int = hs_fig.dpi,
|
|
2310
|
+
save_path: str = None,
|
|
2311
|
+
callback: any = None,
|
|
2312
|
+
) -> None:
|
|
2313
|
+
"""연속형 데이터의 분포를 KDE와 Boxplot으로 시각화한다.
|
|
2314
|
+
|
|
2315
|
+
1행 2열의 서브플롯을 생성하여:
|
|
2316
|
+
- 왼쪽: KDE with 신뢰구간
|
|
2317
|
+
- 오른쪽: Boxplot
|
|
2318
|
+
|
|
2319
|
+
Args:
|
|
2320
|
+
data (DataFrame): 시각화할 데이터.
|
|
2321
|
+
column (str): 분석할 컬럼명.
|
|
2322
|
+
clevel (float): KDE 신뢰수준 (0~1). 기본값 0.95.
|
|
2323
|
+
orient (str): Boxplot 방향 ('v' 또는 'h'). 기본값 'h'.
|
|
2324
|
+
hue (str|None): 명목형 컬럼명. 지정하면 각 범주별로 행을 늘려 KDE와 boxplot을 그림.
|
|
2325
|
+
kind (str): 두 번째 그래프의 유형 (boxplot, hist). 기본값 "boxplot".
|
|
2326
|
+
width (int): 캔버스 가로 픽셀.
|
|
2327
|
+
height (int): 캔버스 세로 픽셀.
|
|
2328
|
+
linewidth (float): 선 굵기.
|
|
2329
|
+
dpi (int): 그림 크기 및 해상도.
|
|
2330
|
+
save_path (str|None): 저장 경로.
|
|
2331
|
+
callback (Callable|None): Axes 후처리 콜백.
|
|
2332
|
+
|
|
2333
|
+
Returns:
|
|
2334
|
+
None
|
|
2335
|
+
"""
|
|
2336
|
+
if hue is None:
|
|
2337
|
+
# 1행 2열 서브플롯 생성
|
|
2338
|
+
fig, axes = get_default_ax(width, height, rows=1, cols=2, dpi=dpi)
|
|
2339
|
+
|
|
2340
|
+
kde_confidence_interval(
|
|
2341
|
+
data=data,
|
|
2342
|
+
xnames=column,
|
|
2343
|
+
clevel=clevel,
|
|
2344
|
+
linewidth=linewidth,
|
|
2345
|
+
ax=axes[0],
|
|
2346
|
+
)
|
|
2347
|
+
|
|
2348
|
+
if kind == "hist":
|
|
2349
|
+
histplot(
|
|
2350
|
+
df=data,
|
|
2351
|
+
xname=column,
|
|
2352
|
+
linewidth=linewidth,
|
|
2353
|
+
ax=axes[1]
|
|
2354
|
+
)
|
|
2355
|
+
else:
|
|
2356
|
+
boxplot(
|
|
2357
|
+
df=data[column],
|
|
2358
|
+
linewidth=linewidth,
|
|
2359
|
+
ax=axes[1]
|
|
2360
|
+
)
|
|
2361
|
+
|
|
2362
|
+
fig.suptitle(f"Distribution of {column}", fontsize=14, y=1.02)
|
|
2363
|
+
else:
|
|
2364
|
+
if hue not in data.columns:
|
|
2365
|
+
raise ValueError(f"hue column '{hue}' not found in DataFrame")
|
|
2366
|
+
|
|
2367
|
+
categories = list(pd.Series(data[hue].dropna().unique()).sort_values())
|
|
2368
|
+
n_cat = len(categories) if categories else 1
|
|
2369
|
+
|
|
2370
|
+
fig, axes = get_default_ax(width, height, rows=n_cat, cols=2, dpi=dpi)
|
|
2371
|
+
axes_2d = np.atleast_2d(axes)
|
|
2372
|
+
|
|
2373
|
+
for idx, cat in enumerate(categories):
|
|
2374
|
+
subset = data[data[hue] == cat]
|
|
2375
|
+
left_ax, right_ax = axes_2d[idx, 0], axes_2d[idx, 1]
|
|
2376
|
+
|
|
2377
|
+
kde_confidence_interval(
|
|
2378
|
+
data=subset,
|
|
2379
|
+
xnames=column,
|
|
2380
|
+
clevel=clevel,
|
|
2381
|
+
linewidth=linewidth,
|
|
2382
|
+
ax=left_ax,
|
|
2383
|
+
)
|
|
2384
|
+
left_ax.set_title(f"{hue} = {cat}")
|
|
2385
|
+
|
|
2386
|
+
if kind == "hist":
|
|
2387
|
+
histplot(
|
|
2388
|
+
df=subset,
|
|
2389
|
+
xname=column,
|
|
2390
|
+
linewidth=linewidth,
|
|
2391
|
+
ax=right_ax,
|
|
2392
|
+
)
|
|
2393
|
+
else:
|
|
2394
|
+
boxplot(
|
|
2395
|
+
df=subset[column],
|
|
2396
|
+
linewidth=linewidth,
|
|
2397
|
+
ax=right_ax
|
|
2398
|
+
)
|
|
2399
|
+
|
|
2400
|
+
fig.suptitle(f"Distribution of {column} by {hue}", fontsize=14, y=1.02)
|
|
2401
|
+
|
|
2402
|
+
plt.tight_layout()
|
|
2403
|
+
|
|
2404
|
+
if save_path:
|
|
2405
|
+
plt.savefig(save_path, bbox_inches='tight', dpi=dpi)
|
|
2406
|
+
plt.close()
|
|
2407
|
+
else:
|
|
2408
|
+
plt.show()
|