hossam 0.3.20__py3-none-any.whl → 0.4.1__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 +21 -26
- hossam/data_loader.py +16 -10
- hossam/hs_classroom.py +48 -38
- hossam/hs_gis.py +10 -6
- hossam/hs_plot.py +153 -150
- hossam/hs_prep.py +95 -85
- hossam/hs_stats.py +426 -548
- hossam/hs_timeserise.py +161 -152
- hossam/hs_util.py +44 -17
- {hossam-0.3.20.dist-info → hossam-0.4.1.dist-info}/METADATA +6 -107
- hossam-0.4.1.dist-info/RECORD +16 -0
- hossam/mcp/__init__.py +0 -12
- hossam/mcp/hs_classroom.py +0 -22
- hossam/mcp/hs_gis.py +0 -30
- hossam/mcp/hs_plot.py +0 -53
- hossam/mcp/hs_prep.py +0 -61
- hossam/mcp/hs_stats.py +0 -25
- hossam/mcp/hs_timeserise.py +0 -22
- hossam/mcp/hs_util.py +0 -30
- hossam/mcp/loader.py +0 -29
- hossam/mcp/server.py +0 -675
- hossam-0.3.20.dist-info/RECORD +0 -27
- hossam-0.3.20.dist-info/entry_points.txt +0 -2
- {hossam-0.3.20.dist-info → hossam-0.4.1.dist-info}/WHEEL +0 -0
- {hossam-0.3.20.dist-info → hossam-0.4.1.dist-info}/licenses/LICENSE +0 -0
- {hossam-0.3.20.dist-info → hossam-0.4.1.dist-info}/top_level.txt +0 -0
hossam/__init__.py
CHANGED
|
@@ -1,33 +1,30 @@
|
|
|
1
|
+
# submodules
|
|
2
|
+
from . import hs_classroom
|
|
3
|
+
from . import hs_gis
|
|
4
|
+
from . import hs_plot
|
|
5
|
+
from . import hs_prep
|
|
6
|
+
from . import hs_stats
|
|
7
|
+
from . import hs_timeserise
|
|
8
|
+
from . import hs_util
|
|
1
9
|
from .data_loader import load_data, load_info
|
|
2
|
-
|
|
10
|
+
|
|
11
|
+
# py-modules
|
|
12
|
+
import sys
|
|
13
|
+
import warnings
|
|
3
14
|
from matplotlib import pyplot as plt
|
|
4
15
|
from matplotlib import font_manager as fm
|
|
5
16
|
from importlib.resources import files, as_file
|
|
6
17
|
from importlib.metadata import version
|
|
7
|
-
from types import SimpleNamespace
|
|
8
|
-
import sys
|
|
9
|
-
import warnings
|
|
10
18
|
|
|
11
19
|
try:
|
|
12
20
|
__version__ = version("hossam")
|
|
13
21
|
except Exception:
|
|
14
22
|
__version__ = "develop"
|
|
15
23
|
|
|
24
|
+
__all__ = ["load_data", "load_info", "hs_classroom", "hs_gis", "hs_plot", "hs_prep", "hs_stats", "hs_timeserise", "hs_util"]
|
|
16
25
|
|
|
17
|
-
hs_fig
|
|
18
|
-
|
|
19
|
-
width=800,
|
|
20
|
-
height=450,
|
|
21
|
-
font_size=9.5,
|
|
22
|
-
font_weight="normal",
|
|
23
|
-
frame_width=0.7,
|
|
24
|
-
line_width=1.5,
|
|
25
|
-
grid_alpha=0.3,
|
|
26
|
-
grid_width=0.5,
|
|
27
|
-
fill_alpha=0.3
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
__all__ = ["load_data", "load_info", "hs_classroom", "hs_gis", "hs_plot", "hs_prep", "hs_stats", "hs_timeserise", "hs_util", "hs_fig"]
|
|
26
|
+
# 내부 모듈에서 hs_fig를 사용할 때는 아래와 같이 import 하세요.
|
|
27
|
+
# from hossam import hs_fig
|
|
31
28
|
|
|
32
29
|
|
|
33
30
|
def _init_korean_font():
|
|
@@ -44,14 +41,14 @@ def _init_korean_font():
|
|
|
44
41
|
|
|
45
42
|
plt.rcParams.update({
|
|
46
43
|
"font.family": fname,
|
|
47
|
-
"font.size":
|
|
48
|
-
"font.weight":
|
|
44
|
+
"font.size": hs_plot.config.font_size,
|
|
45
|
+
"font.weight": hs_plot.config.font_weight,
|
|
49
46
|
"axes.unicode_minus": False,
|
|
50
47
|
"text.antialiased": True,
|
|
51
48
|
"lines.antialiased": True,
|
|
52
49
|
"patch.antialiased": True,
|
|
53
|
-
"figure.dpi":
|
|
54
|
-
"savefig.dpi":
|
|
50
|
+
"figure.dpi": hs_plot.config.dpi,
|
|
51
|
+
"savefig.dpi": hs_plot.config.dpi * 2,
|
|
55
52
|
"text.hinting": "auto",
|
|
56
53
|
"text.hinting_factor": 8,
|
|
57
54
|
"pdf.fonttype": 42,
|
|
@@ -78,10 +75,8 @@ def _init():
|
|
|
78
75
|
f"🔖 Version: {__version__}",
|
|
79
76
|
]
|
|
80
77
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
for msg in messages:
|
|
84
|
-
print(f"{msg}")
|
|
78
|
+
for msg in messages:
|
|
79
|
+
print(f"{msg}")
|
|
85
80
|
|
|
86
81
|
_init_korean_font()
|
|
87
82
|
|
hossam/data_loader.py
CHANGED
|
@@ -39,7 +39,8 @@ def __get_df(path: str, index_col=None) -> DataFrame:
|
|
|
39
39
|
hs_pretty_table(info)
|
|
40
40
|
print()
|
|
41
41
|
except Exception:
|
|
42
|
-
print(f"\033[91m[!] Cannot read metadata\033[0m")
|
|
42
|
+
#print(f"\033[91m[!] Cannot read metadata\033[0m")
|
|
43
|
+
pass
|
|
43
44
|
else:
|
|
44
45
|
df = read_excel(path, index_col=index_col)
|
|
45
46
|
|
|
@@ -51,7 +52,8 @@ def __get_df(path: str, index_col=None) -> DataFrame:
|
|
|
51
52
|
hs_pretty_table(info)
|
|
52
53
|
print()
|
|
53
54
|
except:
|
|
54
|
-
print(f"\033[91m[!] Cannot read metadata\033[0m")
|
|
55
|
+
#print(f"\033[91m[!] Cannot read metadata\033[0m")
|
|
56
|
+
pass
|
|
55
57
|
else:
|
|
56
58
|
df = read_csv(path, index_col=index_col)
|
|
57
59
|
|
|
@@ -105,10 +107,11 @@ def load_info(search: str = None, local: str = None) -> DataFrame:
|
|
|
105
107
|
DataFrame: name, chapter, desc, url 컬럼을 갖는 테이블
|
|
106
108
|
|
|
107
109
|
Examples:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
['name', 'chapter', 'desc', 'url']
|
|
110
|
+
```python
|
|
111
|
+
from hossam import *
|
|
112
|
+
info = load_info()
|
|
113
|
+
list(info.columns) #['name', 'chapter', 'desc', 'url']
|
|
114
|
+
```
|
|
112
115
|
"""
|
|
113
116
|
global BASE_URL
|
|
114
117
|
|
|
@@ -168,8 +171,10 @@ def load_data(key: str, local: str = None) -> Optional[DataFrame]:
|
|
|
168
171
|
DataFrame | None: 성공 시 데이터프레임, 실패 시 None
|
|
169
172
|
|
|
170
173
|
Examples:
|
|
171
|
-
|
|
172
|
-
|
|
174
|
+
```python
|
|
175
|
+
from hossam import *
|
|
176
|
+
df = load_data('AD_SALES') # 메타데이터에 해당 키가 있어야 함
|
|
177
|
+
```
|
|
173
178
|
"""
|
|
174
179
|
index = None
|
|
175
180
|
try:
|
|
@@ -181,8 +186,9 @@ def load_data(key: str, local: str = None) -> Optional[DataFrame]:
|
|
|
181
186
|
print(e)
|
|
182
187
|
return
|
|
183
188
|
|
|
184
|
-
print("\033[94m[data]\033[0m", url.replace("\\", "/"))
|
|
185
|
-
print("\033[94m[desc]\033[0m", desc)
|
|
189
|
+
#print("\033[94m[data]\033[0m", url.replace("\\", "/"))
|
|
190
|
+
#print("\033[94m[desc]\033[0m", desc)
|
|
191
|
+
print(f"\033[94m{desc}\033[0m")
|
|
186
192
|
|
|
187
193
|
df = None
|
|
188
194
|
|
hossam/hs_classroom.py
CHANGED
|
@@ -8,8 +8,8 @@ from kmodes.kmodes import KModes
|
|
|
8
8
|
from matplotlib import pyplot as plt
|
|
9
9
|
import seaborn as sns
|
|
10
10
|
from .hs_util import load_data, pretty_table
|
|
11
|
-
from . import hs_fig
|
|
12
11
|
from . import hs_plot
|
|
12
|
+
from .hs_plot import config
|
|
13
13
|
|
|
14
14
|
# ===================================================================
|
|
15
15
|
# 학생들을 관심사와 성적으로 균형잡힌 조로 편성한다
|
|
@@ -50,13 +50,16 @@ def cluster_students(
|
|
|
50
50
|
ValueError: 필수 컬럼이 없거나 입력값이 유효하지 않은 경우.
|
|
51
51
|
|
|
52
52
|
Examples:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
```python
|
|
54
|
+
df = read_csv('students.csv')
|
|
55
|
+
|
|
56
|
+
from hossam import *
|
|
57
|
+
result = hs_classroom.cluster_students(
|
|
58
|
+
df=df,
|
|
59
|
+
n_groups=5,
|
|
60
|
+
score_cols=['국어', '영어', '수학'],
|
|
61
|
+
interest_col='관심사')
|
|
62
|
+
```
|
|
60
63
|
"""
|
|
61
64
|
|
|
62
65
|
# 파일 경로인 경우 데이터프레임으로 로드
|
|
@@ -389,21 +392,24 @@ def _balance_group_sizes_only(
|
|
|
389
392
|
# ===================================================================
|
|
390
393
|
# 조 편성 결과의 인원, 관심사, 점수 분포를 시각화한다
|
|
391
394
|
# ===================================================================
|
|
392
|
-
def report_summary(df: DataFrame, width: int =
|
|
395
|
+
def report_summary(df: DataFrame, interest_col: str = None, width: int = config.width, height: int = config.height, dpi: int = config.dpi) -> None:
|
|
393
396
|
"""조 편성 결과의 요약 통계를 시각화합니다.
|
|
394
397
|
|
|
395
398
|
조별 인원 분포, 관심사 분포, 평균점수 분포를 나타냅니다.
|
|
396
399
|
|
|
397
400
|
Args:
|
|
398
|
-
df: cluster_students 함수의 반환 결과 데이터프레임.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
401
|
+
df (DataFrame): cluster_students 함수의 반환 결과 데이터프레임.
|
|
402
|
+
interest_col (str): 관심사 컬럼명
|
|
403
|
+
width (int): 그래프 넓이. 기본값: config.width
|
|
404
|
+
height (int): 그래프 높이. 기본값: config.height
|
|
405
|
+
dpi (int): 그래프 해상도. 기본값: config.dpi
|
|
402
406
|
|
|
403
407
|
Examples:
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
408
|
+
```python
|
|
409
|
+
from hossam import *
|
|
410
|
+
df_result = hs_classroom.cluster_students(df, n_groups=5, score_cols=['국어', '영어', '수학'])
|
|
411
|
+
hs_classroom.report_summary(df_result)
|
|
412
|
+
```
|
|
407
413
|
"""
|
|
408
414
|
|
|
409
415
|
if df is None or len(df) == 0:
|
|
@@ -420,7 +426,7 @@ def report_summary(df: DataFrame, width: int = hs_fig.width, height: int = hs_fi
|
|
|
420
426
|
# 필요한 컬럼 확인
|
|
421
427
|
has_score = '총점' in df.columns
|
|
422
428
|
has_avg = '평균점수' in df.columns
|
|
423
|
-
has_interest = '관심사' in df.columns
|
|
429
|
+
has_interest = interest_col and '관심사' in df.columns
|
|
424
430
|
|
|
425
431
|
# 혼합 타입 안전 정렬 라벨 준비
|
|
426
432
|
labels = df['조'].unique().tolist()
|
|
@@ -540,7 +546,7 @@ def report_summary(df: DataFrame, width: int = hs_fig.width, height: int = hs_fi
|
|
|
540
546
|
# ===================================================================
|
|
541
547
|
# 조별 점수 분포를 커널 밀도 추정(KDE) 그래프로 시각화한다
|
|
542
548
|
# ===================================================================
|
|
543
|
-
def report_kde(df: DataFrame, metric: str = 'average', width: int =
|
|
549
|
+
def report_kde(df: DataFrame, metric: str = 'average', width: int = config.width, height: int = config.height, dpi: int = config.dpi) -> None:
|
|
544
550
|
"""조별 점수 분포를 KDE(Kernel Density Estimation)로 시각화합니다.
|
|
545
551
|
|
|
546
552
|
각 조의 점수 분포를 커널 밀도 추정으로 표시하고 평균 및 95% 신뢰구간을 나타냅니다.
|
|
@@ -549,14 +555,16 @@ def report_kde(df: DataFrame, metric: str = 'average', width: int = hs_fig.width
|
|
|
549
555
|
df: cluster_students 함수의 반환 결과 데이터프레임.
|
|
550
556
|
metric: 점수 기준 선택 ('total' 또는 'average').
|
|
551
557
|
'total'이면 총점, 'average'이면 평균점수. 기본값: 'average'
|
|
552
|
-
width: 그래프 넓이. 기본값:
|
|
553
|
-
height: 그래프 높이. 기본값:
|
|
554
|
-
dpi: 그래프 해상도. 기본값:
|
|
558
|
+
width: 그래프 넓이. 기본값: config.width
|
|
559
|
+
height: 그래프 높이. 기본값: config.height
|
|
560
|
+
dpi: 그래프 해상도. 기본값: config.dpi
|
|
555
561
|
|
|
556
562
|
Examples:
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
563
|
+
```python
|
|
564
|
+
from hossam import *
|
|
565
|
+
df_result = hs_classroom.cluster_students(df, n_groups=5, score_cols=['국어', '영어', '수학'])
|
|
566
|
+
hs_classroom.report_kde(df_result, metric='average')
|
|
567
|
+
```
|
|
560
568
|
"""
|
|
561
569
|
if df is None or len(df) == 0:
|
|
562
570
|
print("데이터프레임이 비어있습니다")
|
|
@@ -626,10 +634,12 @@ def group_summary(df: DataFrame, name_col: str = '학생이름') -> DataFrame:
|
|
|
626
634
|
컬럼: '조', '학생', '총점평균', '평균점수평균'
|
|
627
635
|
|
|
628
636
|
Examples:
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
637
|
+
```python
|
|
638
|
+
from hossam import *
|
|
639
|
+
df_result = hs_classroom.cluster_students(df, n_groups=5, score_cols=['국어', '영어', '수학'])
|
|
640
|
+
summary = hs_classroom.group_summary(df_result, name_col='이름')
|
|
641
|
+
print(summary)
|
|
642
|
+
```
|
|
633
643
|
"""
|
|
634
644
|
|
|
635
645
|
if df is None or len(df) == 0:
|
|
@@ -713,15 +723,15 @@ def analyze_classroom(
|
|
|
713
723
|
조별 요약 정보 (group_summary의 결과).
|
|
714
724
|
|
|
715
725
|
Examples:
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
726
|
+
```python
|
|
727
|
+
from hossam import *
|
|
728
|
+
summary = hs_classroom.analyze_classroom(df='students.csv',
|
|
729
|
+
n_groups=5,
|
|
730
|
+
score_cols=['국어', '영어', '수학'],
|
|
731
|
+
interest_col='관심사',
|
|
732
|
+
name_col='이름')
|
|
733
|
+
print(summary)
|
|
734
|
+
```
|
|
725
735
|
"""
|
|
726
736
|
|
|
727
737
|
# 1. 조 편성
|
|
@@ -738,7 +748,7 @@ def analyze_classroom(
|
|
|
738
748
|
|
|
739
749
|
# 3. 요약 시각화
|
|
740
750
|
if show_summary:
|
|
741
|
-
report_summary(df_result)
|
|
751
|
+
report_summary(df_result, interest_col)
|
|
742
752
|
|
|
743
753
|
# 4. KDE 시각화
|
|
744
754
|
if show_kde:
|
hossam/hs_gis.py
CHANGED
|
@@ -101,10 +101,12 @@ def geocode(df: DataFrame, addr: str, key: str) -> DataFrame:
|
|
|
101
101
|
Exception: 지오코딩 과정에서 발생한 예외를 전파합니다.
|
|
102
102
|
|
|
103
103
|
Examples:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
```python
|
|
105
|
+
from hossam import *
|
|
106
|
+
result = hs_gis.geocode(df, addr="address", key="YOUR_VWORLD_KEY")
|
|
107
|
+
set(["latitude","longitude"]).issubset(result.columns)
|
|
108
|
+
# True
|
|
109
|
+
```
|
|
108
110
|
"""
|
|
109
111
|
data: DataFrame = df.copy()
|
|
110
112
|
size: int = len(data)
|
|
@@ -172,8 +174,10 @@ def load_shape(path: str, info: bool = True) -> GeoDataFrame:
|
|
|
172
174
|
FileNotFoundError: 파일이 존재하지 않는 경우.
|
|
173
175
|
|
|
174
176
|
Examples:
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
```python
|
|
178
|
+
from hossam import *
|
|
179
|
+
gdf = hs_gis.load_shape("path/to/file.shp", info=False)
|
|
180
|
+
```
|
|
177
181
|
"""
|
|
178
182
|
if not os.path.exists(path):
|
|
179
183
|
raise FileNotFoundError("⚠️[FileNotFoundException] 주어진 파일을 찾을 수 없습니다.\n - %s" % path)
|