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/__init__.py
CHANGED
|
@@ -6,7 +6,8 @@ from . import hs_prep
|
|
|
6
6
|
from . import hs_stats
|
|
7
7
|
from . import hs_timeserise
|
|
8
8
|
from . import hs_util
|
|
9
|
-
from .
|
|
9
|
+
from .hs_util import load_info
|
|
10
|
+
from .hs_util import _load_data_remote as load_data
|
|
10
11
|
|
|
11
12
|
# py-modules
|
|
12
13
|
import sys
|
hossam/hs_classroom.py
CHANGED
|
@@ -15,10 +15,10 @@ from .hs_plot import config
|
|
|
15
15
|
# 학생들을 관심사와 성적으로 균형잡힌 조로 편성한다
|
|
16
16
|
# ===================================================================
|
|
17
17
|
def cluster_students(
|
|
18
|
-
df,
|
|
18
|
+
df: DataFrame | str,
|
|
19
19
|
n_groups: int,
|
|
20
|
-
score_cols: list = None,
|
|
21
|
-
interest_col: str = None,
|
|
20
|
+
score_cols: list | None = None,
|
|
21
|
+
interest_col: str | None = None,
|
|
22
22
|
max_iter: int = 200,
|
|
23
23
|
score_metric: str = 'total'
|
|
24
24
|
) -> DataFrame:
|
|
@@ -173,7 +173,7 @@ def cluster_students(
|
|
|
173
173
|
df_main,
|
|
174
174
|
actual_n_groups,
|
|
175
175
|
score_cols,
|
|
176
|
-
interest_col,
|
|
176
|
+
interest_col, # type: ignore
|
|
177
177
|
max_iter
|
|
178
178
|
)
|
|
179
179
|
else:
|
|
@@ -219,8 +219,8 @@ def cluster_students(
|
|
|
219
219
|
def _balance_groups(
|
|
220
220
|
df: DataFrame,
|
|
221
221
|
n_groups: int,
|
|
222
|
-
score_cols: list,
|
|
223
|
-
interest_col: str = None,
|
|
222
|
+
score_cols: list | None = None,
|
|
223
|
+
interest_col: str | None = None,
|
|
224
224
|
max_iter: int = 200
|
|
225
225
|
) -> DataFrame:
|
|
226
226
|
"""조 내 인원과 성적 균형을 조정하는 내부 함수.
|
|
@@ -281,7 +281,7 @@ def _balance_groups(
|
|
|
281
281
|
count = grade_counts.loc[g, grade]
|
|
282
282
|
min_g, max_g = grade_bounds[grade]
|
|
283
283
|
|
|
284
|
-
if count <= max_g:
|
|
284
|
+
if count <= max_g: # type: ignore
|
|
285
285
|
continue
|
|
286
286
|
|
|
287
287
|
donors = group[group['성적그룹'] == grade]
|
|
@@ -291,12 +291,12 @@ def _balance_groups(
|
|
|
291
291
|
if og == g:
|
|
292
292
|
continue
|
|
293
293
|
other_count = grade_counts.loc[og, grade]
|
|
294
|
-
if other_count >= min_g:
|
|
294
|
+
if other_count >= min_g: # type: ignore
|
|
295
295
|
continue
|
|
296
296
|
other_group = df[df['조'] == og]
|
|
297
297
|
|
|
298
298
|
og_interest = dominant_interest(other_group)
|
|
299
|
-
need_groups.append((min_g - other_count, og, og_interest))
|
|
299
|
+
need_groups.append((min_g - other_count, og, og_interest)) # type: ignore
|
|
300
300
|
|
|
301
301
|
need_groups.sort(reverse=True)
|
|
302
302
|
|
|
@@ -392,14 +392,14 @@ def _balance_group_sizes_only(
|
|
|
392
392
|
# ===================================================================
|
|
393
393
|
# 조 편성 결과의 인원, 관심사, 점수 분포를 시각화한다
|
|
394
394
|
# ===================================================================
|
|
395
|
-
def report_summary(df: DataFrame, interest_col: str = None, width: int = config.width, height: int = config.height, dpi: int = config.dpi) -> None:
|
|
395
|
+
def report_summary(df: DataFrame, interest_col: str | None = None, width: int = config.width, height: int = config.height, dpi: int = config.dpi) -> None:
|
|
396
396
|
"""조 편성 결과의 요약 통계를 시각화합니다.
|
|
397
397
|
|
|
398
398
|
조별 인원 분포, 관심사 분포, 평균점수 분포를 나타냅니다.
|
|
399
399
|
|
|
400
400
|
Args:
|
|
401
401
|
df (DataFrame): cluster_students 함수의 반환 결과 데이터프레임.
|
|
402
|
-
interest_col (str): 관심사 컬럼명
|
|
402
|
+
interest_col (str | None): 관심사 컬럼명
|
|
403
403
|
width (int): 그래프 넓이. 기본값: config.width
|
|
404
404
|
height (int): 그래프 높이. 기본값: config.height
|
|
405
405
|
dpi (int): 그래프 해상도. 기본값: config.dpi
|
|
@@ -540,24 +540,24 @@ def report_summary(df: DataFrame, interest_col: str = None, width: int = config.
|
|
|
540
540
|
plot_idx += 1
|
|
541
541
|
|
|
542
542
|
# hs_plot.finalize_plot을 사용하여 마무리
|
|
543
|
-
hs_plot.finalize_plot(axes, outparams=True, grid=False)
|
|
543
|
+
hs_plot.finalize_plot(axes, outparams=True, grid=False) # type: ignore
|
|
544
544
|
|
|
545
545
|
|
|
546
546
|
# ===================================================================
|
|
547
547
|
# 조별 점수 분포를 커널 밀도 추정(KDE) 그래프로 시각화한다
|
|
548
548
|
# ===================================================================
|
|
549
|
-
def report_kde(df: DataFrame, metric: str = 'average', width: int = config.width, height: int = config.height, dpi: int = config.dpi) -> None:
|
|
549
|
+
def report_kde(df: DataFrame | str, metric: str = 'average', width: int = config.width, height: int = config.height, dpi: int = config.dpi) -> None:
|
|
550
550
|
"""조별 점수 분포를 KDE(Kernel Density Estimation)로 시각화합니다.
|
|
551
551
|
|
|
552
552
|
각 조의 점수 분포를 커널 밀도 추정으로 표시하고 평균 및 95% 신뢰구간을 나타냅니다.
|
|
553
553
|
|
|
554
554
|
Args:
|
|
555
|
-
df: cluster_students 함수의 반환 결과 데이터프레임.
|
|
556
|
-
metric: 점수 기준 선택 ('total' 또는 'average').
|
|
555
|
+
df (DataFrame | str): cluster_students 함수의 반환 결과 데이터프레임.
|
|
556
|
+
metric (str): 점수 기준 선택 ('total' 또는 'average').
|
|
557
557
|
'total'이면 총점, 'average'이면 평균점수. 기본값: 'average'
|
|
558
|
-
width: 그래프 넓이. 기본값: config.width
|
|
559
|
-
height: 그래프 높이. 기본값: config.height
|
|
560
|
-
dpi: 그래프 해상도. 기본값: config.dpi
|
|
558
|
+
width (int): 그래프 넓이. 기본값: config.width
|
|
559
|
+
height (int): 그래프 높이. 기본값: config.height
|
|
560
|
+
dpi (int): 그래프 해상도. 기본값: config.dpi
|
|
561
561
|
|
|
562
562
|
Examples:
|
|
563
563
|
```python
|
|
@@ -570,17 +570,17 @@ def report_kde(df: DataFrame, metric: str = 'average', width: int = config.width
|
|
|
570
570
|
print("데이터프레임이 비어있습니다")
|
|
571
571
|
return
|
|
572
572
|
|
|
573
|
-
if '조' not in df.columns:
|
|
573
|
+
if '조' not in df.columns: # type: ignore
|
|
574
574
|
print("데이터프레임에 '조' 컬럼이 없습니다")
|
|
575
575
|
return
|
|
576
576
|
|
|
577
|
-
has_score = '총점' in df.columns
|
|
578
|
-
has_avg = '평균점수' in df.columns
|
|
577
|
+
has_score = '총점' in df.columns # type: ignore
|
|
578
|
+
has_avg = '평균점수' in df.columns # type: ignore
|
|
579
579
|
if not has_score:
|
|
580
580
|
print("점수 데이터가 없습니다")
|
|
581
581
|
return
|
|
582
582
|
|
|
583
|
-
labels = df['조'].unique().tolist()
|
|
583
|
+
labels = df['조'].unique().tolist() # type: ignore
|
|
584
584
|
def _sort_key(v):
|
|
585
585
|
try:
|
|
586
586
|
return (0, int(v))
|
|
@@ -596,18 +596,18 @@ def report_kde(df: DataFrame, metric: str = 'average', width: int = config.width
|
|
|
596
596
|
|
|
597
597
|
plot_idx = 0
|
|
598
598
|
metric_col = '평균점수' if (metric or '').lower() == 'average' else '총점'
|
|
599
|
-
if metric_col not in df.columns:
|
|
599
|
+
if metric_col not in df.columns: # type: ignore
|
|
600
600
|
print(f"'{metric_col}' 컬럼이 없습니다")
|
|
601
601
|
return
|
|
602
602
|
|
|
603
603
|
for group in ordered_labels:
|
|
604
|
-
group_df = df[df['조'] == group]
|
|
605
|
-
group_series = group_df[metric_col].dropna()
|
|
604
|
+
group_df = df[df['조'] == group] # type: ignore
|
|
605
|
+
group_series = group_df[metric_col].dropna() # type: ignore
|
|
606
606
|
n = group_series.size
|
|
607
607
|
if n == 0:
|
|
608
608
|
continue
|
|
609
609
|
|
|
610
|
-
hs_plot.kde_confidence_interval(data=group_df, xnames=metric_col, ax=axes[plot_idx], callback=lambda ax: ax.set_title(f"{group}조"))
|
|
610
|
+
hs_plot.kde_confidence_interval(data=group_df, xnames=metric_col, ax=axes[plot_idx], callback=lambda ax: ax.set_title(f"{group}조")) # type: ignore
|
|
611
611
|
|
|
612
612
|
plot_idx += 1
|
|
613
613
|
|
|
@@ -615,7 +615,7 @@ def report_kde(df: DataFrame, metric: str = 'average', width: int = config.width
|
|
|
615
615
|
for idx in range(plot_idx, len(axes)):
|
|
616
616
|
fig.delaxes(axes[idx])
|
|
617
617
|
|
|
618
|
-
hs_plot.finalize_plot(axes)
|
|
618
|
+
hs_plot.finalize_plot(axes) # type: ignore
|
|
619
619
|
|
|
620
620
|
|
|
621
621
|
# ===================================================================
|
|
@@ -690,10 +690,10 @@ def group_summary(df: DataFrame, name_col: str = '학생이름') -> DataFrame:
|
|
|
690
690
|
# 학생 조 편성부터 시각화까지의 전체 분석 프로세스를 일괄 실행한다
|
|
691
691
|
# ===================================================================
|
|
692
692
|
def analyze_classroom(
|
|
693
|
-
df,
|
|
693
|
+
df: DataFrame | str,
|
|
694
694
|
n_groups: int,
|
|
695
|
-
score_cols: list = None,
|
|
696
|
-
interest_col: str = None,
|
|
695
|
+
score_cols: list | None = None,
|
|
696
|
+
interest_col: str | None = None,
|
|
697
697
|
max_iter: int = 200,
|
|
698
698
|
score_metric: str = 'average',
|
|
699
699
|
name_col: str = '학생이름',
|
hossam/hs_gis.py
CHANGED
|
@@ -22,10 +22,10 @@ def __geocode_item(session: requests.Session, index: int, addr: str, key: str) -
|
|
|
22
22
|
"""단일 주소를 VWorld API로 지오코딩합니다.
|
|
23
23
|
|
|
24
24
|
Args:
|
|
25
|
-
session: 재사용할 `requests.Session` 인스턴스.
|
|
26
|
-
index: 입력 데이터의 인덱스(로그용).
|
|
27
|
-
addr: 지오코딩할 도로명 주소 문자열.
|
|
28
|
-
key: VWorld API 키.
|
|
25
|
+
session (requests.Session): 재사용할 `requests.Session` 인스턴스.
|
|
26
|
+
index (int): 입력 데이터의 인덱스(로그용).
|
|
27
|
+
addr (str): 지오코딩할 도로명 주소 문자열.
|
|
28
|
+
key (str): VWorld API 키.
|
|
29
29
|
|
|
30
30
|
Returns:
|
|
31
31
|
(latitude, longitude) 튜플.
|
|
@@ -90,12 +90,12 @@ def geocode(df: DataFrame, addr: str, key: str) -> DataFrame:
|
|
|
90
90
|
"""주소 컬럼을 일괄 지오코딩하여 위도/경도 컬럼을 추가합니다.
|
|
91
91
|
|
|
92
92
|
Args:
|
|
93
|
-
df: 입력 `DataFrame`.
|
|
94
|
-
addr: 주소가 들어있는 컬럼명.
|
|
95
|
-
key: VWorld API 키.
|
|
93
|
+
df (DataFrame): 입력 `DataFrame`.
|
|
94
|
+
addr (str): 주소가 들어있는 컬럼명.
|
|
95
|
+
key (str): VWorld API 키.
|
|
96
96
|
|
|
97
97
|
Returns:
|
|
98
|
-
위도(`latitude`), 경도(`longitude`) 컬럼이 추가된 `DataFrame`.
|
|
98
|
+
DataFrame: 위도(`latitude`), 경도(`longitude`) 컬럼이 추가된 `DataFrame`.
|
|
99
99
|
|
|
100
100
|
Raises:
|
|
101
101
|
Exception: 지오코딩 과정에서 발생한 예외를 전파합니다.
|
|
@@ -164,11 +164,11 @@ def load_shape(path: str, info: bool = True) -> GeoDataFrame:
|
|
|
164
164
|
"""Shapefile을 읽어 `GeoDataFrame`으로 로드합니다.
|
|
165
165
|
|
|
166
166
|
Args:
|
|
167
|
-
path: 읽을 Shapefile(.shp) 경로.
|
|
168
|
-
info: True면 데이터 프리뷰와 통계를 출력.
|
|
167
|
+
path (str): 읽을 Shapefile(.shp) 경로.
|
|
168
|
+
info (bool): True면 데이터 프리뷰와 통계를 출력.
|
|
169
169
|
|
|
170
170
|
Returns:
|
|
171
|
-
로드된 `GeoDataFrame`.
|
|
171
|
+
GeoDataFrame: 로드된 `GeoDataFrame`.
|
|
172
172
|
|
|
173
173
|
Raises:
|
|
174
174
|
FileNotFoundError: 파일이 존재하지 않는 경우.
|
|
@@ -186,7 +186,7 @@ def load_shape(path: str, info: bool = True) -> GeoDataFrame:
|
|
|
186
186
|
|
|
187
187
|
if info:
|
|
188
188
|
print("\n✅ 테이블 정보")
|
|
189
|
-
pretty_table(data.info(), tablefmt="pretty")
|
|
189
|
+
pretty_table(data.info(), tablefmt="pretty") # type: ignore
|
|
190
190
|
|
|
191
191
|
print("\n✅ 상위 5개 행")
|
|
192
192
|
pretty_table(data.head(), tablefmt="pretty")
|
|
@@ -226,12 +226,11 @@ def save_shape(
|
|
|
226
226
|
- 확장자 없으면 .shp로 저장
|
|
227
227
|
|
|
228
228
|
Args:
|
|
229
|
-
gdf: 저장할 `GeoDataFrame` 또는 `DataFrame`.
|
|
230
|
-
path: 저장 경로(.shp 또는 .gpkg, 확장자 없으면 .shp 자동 추가).
|
|
231
|
-
crs: 좌표계 문자열(e.g., "EPSG:4326"). 미지정 시 WGS84.
|
|
232
|
-
lat_col: DataFrame 입력 시 위도 컬럼명.
|
|
233
|
-
lon_col: DataFrame 입력 시 경도 컬럼명.
|
|
234
|
-
|
|
229
|
+
gdf (GeoDataFrame | DataFrame): 저장할 `GeoDataFrame` 또는 `DataFrame`.
|
|
230
|
+
path (str): 저장 경로(.shp 또는 .gpkg, 확장자 없으면 .shp 자동 추가).
|
|
231
|
+
crs (str | None): 좌표계 문자열(e.g., "EPSG:4326"). 미지정 시 WGS84.
|
|
232
|
+
lat_col (str): DataFrame 입력 시 위도 컬럼명.
|
|
233
|
+
lon_col (str): DataFrame 입력 시 경도 컬럼명.
|
|
235
234
|
Returns:
|
|
236
235
|
None: 파일을 저장하고 반환값이 없습니다.
|
|
237
236
|
|