Skip to content

Commit 943a162

Browse files
committed
feat: add more 4 charts
1 parent 93b7766 commit 943a162

24 files changed

Lines changed: 637 additions & 1 deletion
63.1 KB
Loading
50.9 KB
Loading
61.8 KB
Loading
126 KB
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Age distribution charts package."""
270 Bytes
Binary file not shown.
4.43 KB
Binary file not shown.
Binary file not shown.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""
2+
Chart 7: Age Group Distribution - Interactions
3+
Type of Chart: Grouped vertical bar chart
4+
Data Points:
5+
- demographic.csv: demo_age_5_17, demo_age_17_
6+
- biometric.csv: bio_age_5_17, bio_age_17_
7+
- 4 bars: 5-17 (Demo), 18+ (Demo), 5-17 (Bio), 18+ (Bio)
8+
"""
9+
import matplotlib.pyplot as plt
10+
import numpy as np
11+
12+
from src.charts import register_chart
13+
from src.charts.base import BaseChart
14+
from src.processors import AgeGroupAggregator
15+
import config
16+
17+
18+
@register_chart
19+
class Chart07AgeGroupInteractions(BaseChart):
20+
21+
@property
22+
def chart_id(self) -> str:
23+
return "07"
24+
25+
@property
26+
def title(self) -> str:
27+
return "Age Group Distribution - Interactions"
28+
29+
def generate(self) -> plt.Figure:
30+
data = self.data_loader.get_all_data()
31+
processor = AgeGroupAggregator()
32+
age_data = processor.process_interactions(data)
33+
34+
fig, ax = plt.subplots(figsize=(12, 8))
35+
36+
# Set up bar positions
37+
x = np.arange(len(age_data))
38+
width = 0.6
39+
40+
# Create bars with different colors for demo vs bio
41+
colors = [
42+
config.COLORS["demographic"], # 5-17 (Demo)
43+
config.COLORS["demographic"], # 18+ (Demo)
44+
config.COLORS["biometric"], # 5-17 (Bio)
45+
config.COLORS["biometric"], # 18+ (Bio)
46+
]
47+
48+
bars = ax.bar(
49+
x,
50+
age_data["total"],
51+
width,
52+
color=colors,
53+
edgecolor="white",
54+
linewidth=1.5,
55+
alpha=0.8
56+
)
57+
58+
# Add value labels on top of bars
59+
for i, (bar, row) in enumerate(zip(bars, age_data.itertuples())):
60+
height = bar.get_height()
61+
# Format in millions
62+
value_text = f"{row.total/1e6:.1f}M"
63+
percentage_text = f"({row.percentage:.1f}%)"
64+
65+
ax.text(
66+
bar.get_x() + bar.get_width() / 2,
67+
height,
68+
f"{value_text}\n{percentage_text}",
69+
ha="center",
70+
va="bottom",
71+
fontsize=10,
72+
fontweight="bold"
73+
)
74+
75+
self._apply_common_style(ax)
76+
ax.set_xlabel("Age Group by Service Type", fontsize=12)
77+
ax.set_ylabel("Total Interactions", fontsize=12)
78+
ax.set_xticks(x)
79+
ax.set_xticklabels(age_data["category"], fontsize=10)
80+
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"{x/1e6:.0f}M"))
81+
ax.grid(axis="y", alpha=0.3, linestyle="--")
82+
83+
# Add legend
84+
from matplotlib.patches import Patch
85+
legend_elements = [
86+
Patch(facecolor=config.COLORS["demographic"], label="Demographic", alpha=0.8),
87+
Patch(facecolor=config.COLORS["biometric"], label="Biometric", alpha=0.8)
88+
]
89+
ax.legend(handles=legend_elements, loc="upper right", fontsize=10)
90+
91+
fig.tight_layout()
92+
93+
return fig
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
Chart 8: Age Group Distribution - Enrollments
3+
Type of Chart: Vertical bar chart
4+
Data Points:
5+
- enrollment.csv: age_0_5, age_5_17, age_18_greater
6+
- 3 bars: 0-5, 5-17, 18+
7+
"""
8+
import matplotlib.pyplot as plt
9+
import numpy as np
10+
11+
from src.charts import register_chart
12+
from src.charts.base import BaseChart
13+
from src.processors import AgeGroupAggregator
14+
import config
15+
16+
17+
@register_chart
18+
class Chart08AgeGroupEnrollments(BaseChart):
19+
20+
@property
21+
def chart_id(self) -> str:
22+
return "08"
23+
24+
@property
25+
def title(self) -> str:
26+
return "Age Group Distribution - Enrollments"
27+
28+
def generate(self) -> plt.Figure:
29+
data = self.data_loader.get_all_data()
30+
processor = AgeGroupAggregator()
31+
age_data = processor.process_enrollments(data)
32+
33+
fig, ax = plt.subplots(figsize=(10, 8))
34+
35+
# Create bars
36+
bars = ax.bar(
37+
age_data["age_group"],
38+
age_data["total"],
39+
color=config.COLORS["enrollment"],
40+
edgecolor="white",
41+
linewidth=1.5,
42+
alpha=0.8,
43+
width=0.6
44+
)
45+
46+
# Add value labels on top of bars
47+
for bar, row in zip(bars, age_data.itertuples()):
48+
height = bar.get_height()
49+
# Format in thousands or millions
50+
if row.total >= 1e6:
51+
value_text = f"{row.total/1e6:.2f}M"
52+
else:
53+
value_text = f"{row.total/1e3:.0f}K"
54+
55+
percentage_text = f"({row.percentage:.1f}%)"
56+
57+
ax.text(
58+
bar.get_x() + bar.get_width() / 2,
59+
height,
60+
f"{value_text}\n{percentage_text}",
61+
ha="center",
62+
va="bottom",
63+
fontsize=11,
64+
fontweight="bold"
65+
)
66+
67+
self._apply_common_style(ax)
68+
ax.set_xlabel("Age Group", fontsize=12)
69+
ax.set_ylabel("Total Enrollments", fontsize=12)
70+
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"{x/1e6:.1f}M" if x >= 1e6 else f"{x/1e3:.0f}K"))
71+
ax.grid(axis="y", alpha=0.3, linestyle="--")
72+
73+
fig.tight_layout()
74+
75+
return fig

0 commit comments

Comments
 (0)