hossam 0.3.19__py3-none-any.whl → 0.4__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 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
- from .hs_stats import oneway_anova
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 = SimpleNamespace(
18
- dpi=200,
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": hs_fig.font_size,
48
- "font.weight": hs_fig.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": hs_fig.dpi,
54
- "savefig.dpi": hs_fig.dpi * 2,
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,
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
- >>> from hossam.data_loader import load_info
109
- >>> info = load_info()
110
- >>> list(info.columns)
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
- >>> from hossam.data_loader import load_data
172
- >>> df = load_data('AD_SALES') # 메타데이터에 해당 키가 있어야 함
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
- >>> df = read_csv('students.csv')
54
- >>> result = cluster_students(
55
- ... df=df,
56
- ... n_groups=5,
57
- ... score_cols=['국어', '영어', '수학'],
58
- ... interest_col='관심사'
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
  # 파일 경로인 경우 데이터프레임으로 로드
@@ -89,6 +92,11 @@ def cluster_students(
89
92
 
90
93
  # ===== 1단계: 점수 기반 처리 =====
91
94
  if score_cols is not None:
95
+ # 결측치는 0점으로 대체
96
+ for s in score_cols:
97
+ df[s] = df[s].fillna(0)
98
+ print(df)
99
+
92
100
  # 총점/평균점수 계산
93
101
  df['총점'] = df[score_cols].sum(axis=1)
94
102
  df['평균점수'] = df[score_cols].mean(axis=1)
@@ -97,12 +105,22 @@ def cluster_students(
97
105
  metric_col = '총점' if (score_metric or '').lower() != 'average' else '평균점수'
98
106
 
99
107
  # 성적사분위 분류 (선택한 기준 사용)
100
- df['성적사분위'] = qcut(
101
- df[metric_col],
102
- q=[0, 0.25, 0.50, 0.75, 1.0],
103
- labels=['Q1', 'Q2', 'Q3', 'Q4'],
104
- duplicates='drop' # 중복된 값 처리
105
- )
108
+ quantiles = [0, 0.25, 0.50, 0.75, 1.0]
109
+ n_bins = len(quantiles) - 1
110
+ labels = [f"Q{i+1}" for i in range(n_bins)]
111
+ try:
112
+ df['성적사분위'] = qcut(
113
+ df[metric_col],
114
+ q=quantiles,
115
+ labels=labels,
116
+ duplicates='drop' # 중복된 값 처리
117
+ )
118
+ except ValueError:
119
+ # 구간이 줄어든 경우, bins 개수에 맞게 labels 재생성
120
+ import pandas as pd
121
+ bins = pd.qcut(df[metric_col], q=quantiles, duplicates='drop').cat.categories
122
+ labels = [f"Q{i+1}" for i in range(len(bins))]
123
+ df['성적사분위'] = pd.qcut(df[metric_col], q=quantiles, labels=labels, duplicates='drop')
106
124
 
107
125
  # 성적그룹 매핑
108
126
  df['성적그룹'] = df['성적사분위'].map({
@@ -374,21 +392,24 @@ def _balance_group_sizes_only(
374
392
  # ===================================================================
375
393
  # 조 편성 결과의 인원, 관심사, 점수 분포를 시각화한다
376
394
  # ===================================================================
377
- def report_summary(df: DataFrame, width: int = hs_fig.width, height: int = hs_fig.height, dpi: int = hs_fig.dpi) -> None:
395
+ def report_summary(df: DataFrame, interest_col: str = None, width: int = config.width, height: int = config.height, dpi: int = config.dpi) -> None:
378
396
  """조 편성 결과의 요약 통계를 시각화합니다.
379
397
 
380
398
  조별 인원 분포, 관심사 분포, 평균점수 분포를 나타냅니다.
381
399
 
382
400
  Args:
383
- df: cluster_students 함수의 반환 결과 데이터프레임.
384
- width: 그래프 넓이. 기본값: hs_fig.width
385
- height: 그래프 높이. 기본값: hs_fig.height
386
- dpi: 그래프 해상도. 기본값: hs_fig.dpi
401
+ df (DataFrame): cluster_students 함수의 반환 결과 데이터프레임.
402
+ interest_col (str): 관심사 컬럼명
403
+ width (int): 그래프 넓이. 기본값: config.width
404
+ height (int): 그래프 높이. 기본값: config.height
405
+ dpi (int): 그래프 해상도. 기본값: config.dpi
387
406
 
388
407
  Examples:
389
- >>> from hossam.classroom import cluster_students, report_summary
390
- >>> df_result = cluster_students(df, n_groups=5, score_cols=['국어', '영어', '수학'])
391
- >>> report_summary(df_result)
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
+ ```
392
413
  """
393
414
 
394
415
  if df is None or len(df) == 0:
@@ -405,7 +426,7 @@ def report_summary(df: DataFrame, width: int = hs_fig.width, height: int = hs_fi
405
426
  # 필요한 컬럼 확인
406
427
  has_score = '총점' in df.columns
407
428
  has_avg = '평균점수' in df.columns
408
- has_interest = '관심사' in df.columns
429
+ has_interest = interest_col and '관심사' in df.columns
409
430
 
410
431
  # 혼합 타입 안전 정렬 라벨 준비
411
432
  labels = df['조'].unique().tolist()
@@ -525,7 +546,7 @@ def report_summary(df: DataFrame, width: int = hs_fig.width, height: int = hs_fi
525
546
  # ===================================================================
526
547
  # 조별 점수 분포를 커널 밀도 추정(KDE) 그래프로 시각화한다
527
548
  # ===================================================================
528
- def report_kde(df: DataFrame, metric: str = 'average', width: int = hs_fig.width, height: int = hs_fig.height, dpi: int = hs_fig.dpi) -> None:
549
+ def report_kde(df: DataFrame, metric: str = 'average', width: int = config.width, height: int = config.height, dpi: int = config.dpi) -> None:
529
550
  """조별 점수 분포를 KDE(Kernel Density Estimation)로 시각화합니다.
530
551
 
531
552
  각 조의 점수 분포를 커널 밀도 추정으로 표시하고 평균 및 95% 신뢰구간을 나타냅니다.
@@ -534,14 +555,16 @@ def report_kde(df: DataFrame, metric: str = 'average', width: int = hs_fig.width
534
555
  df: cluster_students 함수의 반환 결과 데이터프레임.
535
556
  metric: 점수 기준 선택 ('total' 또는 'average').
536
557
  'total'이면 총점, 'average'이면 평균점수. 기본값: 'average'
537
- width: 그래프 넓이. 기본값: hs_fig.width
538
- height: 그래프 높이. 기본값: hs_fig.height
539
- dpi: 그래프 해상도. 기본값: hs_fig.dpi
558
+ width: 그래프 넓이. 기본값: config.width
559
+ height: 그래프 높이. 기본값: config.height
560
+ dpi: 그래프 해상도. 기본값: config.dpi
540
561
 
541
562
  Examples:
542
- >>> from hossam.classroom import cluster_students, report_kde
543
- >>> df_result = cluster_students(df, n_groups=5, score_cols=['국어', '영어', '수학'])
544
- >>> report_kde(df_result, metric='average')
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
+ ```
545
568
  """
546
569
  if df is None or len(df) == 0:
547
570
  print("데이터프레임이 비어있습니다")
@@ -611,10 +634,12 @@ def group_summary(df: DataFrame, name_col: str = '학생이름') -> DataFrame:
611
634
  컬럼: '조', '학생', '총점평균', '평균점수평균'
612
635
 
613
636
  Examples:
614
- >>> from hossam.classroom import cluster_students, group_summary
615
- >>> df_result = cluster_students(df, n_groups=5, score_cols=['국어', '영어', '수학'])
616
- >>> summary = group_summary(df_result, name_col='이름')
617
- >>> print(summary)
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
+ ```
618
643
  """
619
644
 
620
645
  if df is None or len(df) == 0:
@@ -698,15 +723,15 @@ def analyze_classroom(
698
723
  조별 요약 정보 (group_summary의 결과).
699
724
 
700
725
  Examples:
701
- >>> from hossam.classroom import analyze_classroom
702
- >>> summary = analyze_classroom(
703
- ... df='students.csv',
704
- ... n_groups=5,
705
- ... score_cols=['국어', '영어', '수학'],
706
- ... interest_col='관심사',
707
- ... name_col='이름'
708
- ... )
709
- >>> print(summary)
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
+ ```
710
735
  """
711
736
 
712
737
  # 1. 조 편성
@@ -723,7 +748,7 @@ def analyze_classroom(
723
748
 
724
749
  # 3. 요약 시각화
725
750
  if show_summary:
726
- report_summary(df_result)
751
+ report_summary(df_result, interest_col)
727
752
 
728
753
  # 4. KDE 시각화
729
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
- >>> from hossam import gis
105
- >>> result = gis.hs_geocode(df, addr="address", key="YOUR_VWORLD_KEY")
106
- >>> set(["latitude","longitude"]).issubset(result.columns)
107
- True
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
- >>> from hossam.gis import load_shape
176
- >>> gdf = hs_load_shape("path/to/file.shp", info=False)
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)