Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Poverty charts #35

Merged
merged 3 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added policyengine/charts/__init__.py
Empty file.
65 changes: 65 additions & 0 deletions policyengine/charts/inequality.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import plotly.graph_objects as go
from policyengine_core.charts.formatting import *

class InequalityImpactChart:
def __init__(self, data=None) -> None:
if data is None:
raise ValueError("Data must be provided")

# Expecting data to contain baseline, reform, change, and change_percentage for each metric
self.data = data

def generate_chart_data(self):
# Data for the x-axis labels
metrics = ["Gini index", "Top 1% share", "Top 10% share"]

# Extract the change percentages, baseline, and reform values for hover text
change_percentages = [self.data[metric]['change_percentage'] for metric in metrics]
baseline_values = [self.data[metric]['baseline'] for metric in metrics]
reform_values = [self.data[metric]['reform'] for metric in metrics]

# Generate hover text for each metric
hover_texts = [
f"The reform would increase the {metric} by {change_percentages[i]}% from {baseline_values[i]} to {reform_values[i]}%"
if change_percentages[i] > 0
else f"The reform would decrease the {metric} by {change_percentages[i]}% from {baseline_values[i]} to {reform_values[i]}%"
for i, metric in enumerate(metrics)
]

# Create the bar chart figure
fig = go.Figure()

# Add a bar trace for the change percentages of each metric
fig.add_trace(go.Bar(
x=metrics, # Labels for each metric
y=change_percentages, # Change percentages for each metric
marker=dict(
color=[BLUE if change_percentages[i] > 0 else GRAY for i in range(len(change_percentages))], # Conditional color for each bar
line=dict(width=1),
),
text=[f"{percent}%" for percent in change_percentages], # Display percentage as text
textposition='outside', # Position text outside the bars
hovertemplate=f"<b>%{{x}}</b><br><br>%{{customdata}}<extra></extra>",
customdata=hover_texts # Hover text for each bar
))

# Update layout for the chart
fig.update_layout(
yaxis=dict(
tickformat=".1f", # Show y-values with one decimal place
ticksuffix="%",
title="Relative change" # Add percentage symbol
),
hoverlabel=dict(
bgcolor="white", # Background color of the hover label
font=dict(
color="black", # Text color of the hover label
size=16, # Font size
),
),
title="Impact of Reform on Inequality Metrics" # Add a title to the chart
)

format_fig(fig)

return fig
Empty file.
Empty file.
107 changes: 107 additions & 0 deletions policyengine/charts/poverty/deep/by_age.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import plotly.graph_objects as go
from policyengine_core.charts.formatting import *

class DeepPovertyByAgeChart:
def __init__(self,country:str, data=None):
if data is None:
raise ValueError("Data must be provided")

self.data = data

def _get_color(self, value):
# All bars should be gray
return GRAY

def _get_change_direction(self, value):
if value > 0:
return "increase"
elif value < 0:
return "decrease"
else:
return "no change"

def ordinal_suffix(self, n):
"""Return the ordinal suffix for an integer."""
if 10 <= n % 100 <= 20:
suffix = 'th'
else:
suffix = {1: 'st', 2: 'nd', 3: 'rd'}.get(n % 10, 'th')
return suffix

def generate_chart_data(self):
categories = list(self.data.keys())
values = [self.data[cat]['change'] for cat in categories]
baselines = [self.data[cat]['baseline'] * 100 for cat in categories]
reforms = [self.data[cat]['reform'] * 100 for cat in categories]

# Generate hover texts with baseline, reform, and percentage change
hover_texts = [
f"This reform would {self._get_change_direction(val)} the percentage of {category.lower()} in poverty by {abs(val):.1f}% from {baseline:.1f}% to {reform:.1f}%"
for category, val, baseline, reform in zip(categories, values, baselines, reforms)
]

fig = go.Figure()

values_in_pct = values # Use percentage values
colors = [self._get_color(value) for value in values]

# Add bar chart with percentage values
fig.add_trace(go.Bar(
x=categories,
y=values_in_pct,
marker=dict(color=colors, line=dict(width=1)),
width=0.6,
text=[f"{abs(value):.1f}%" for value in values], # Display values as percentages
textposition='outside',
hovertemplate="<b>%{x}</b><br><br>%{customdata}<extra></extra>", # Hover shows category
customdata=hover_texts
))

# Update layout to reflect percentage values on y-axis
fig.update_layout(
yaxis=dict(
tickformat=",.1f%%", # Format y-axis as percentages with one decimal place
title="Percentage Change in Poverty"
),
xaxis=dict(
title="Category"
),
hoverlabel=dict(
bgcolor="white",
font=dict(color="black", size=16)
),
title="Change in Poverty Percentage by Category"
)

format_fig(fig) # Keep the formatting logic from policyengine_core
return fig


# # Example data
# data = {
# 'Child': {
# 'Baseline': 0.32427219591395395,
# 'Reform': 0.33392168532001054,
# 'Change': 3.0
# },
# 'Adult': {
# 'Baseline': 0.17427822561729264,
# 'Reform': 0.17757158627182623,
# 'Change': 1.9
# },
# 'Senior': {
# 'Baseline': 0.12817646500651358,
# 'Reform': 0.1370685860340031,
# 'Change': 6.9
# },
# 'All': {
# 'Baseline': 0.19913534734369268,
# 'Reform': 0.20487670454940832,
# 'Change': 2.9
# }
# }

# # Generate chart for all categories
# chart = OverallChart(data=data)
# fig = chart.generate_chart_data()
# fig.show()
103 changes: 103 additions & 0 deletions policyengine/charts/poverty/deep/by_gender.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import plotly.graph_objects as go
from policyengine_core.charts.formatting import *

class DeepPovertyByGenderChart:
def __init__(self, country:str,data=None):
if data is None:
raise ValueError("Data must be provided")

self.data = data

def _get_color(self, value):
# All bars should be gray
return GRAY

def _get_change_direction(self, value):
if value > 0:
return "increase"
elif value < 0:
return "decrease"
else:
return "no change"

def ordinal_suffix(self, n):
"""Return the ordinal suffix for an integer."""
if 10 <= n % 100 <= 20:
suffix = 'th'
else:
suffix = {1: 'st', 2: 'nd', 3: 'rd'}.get(n % 10, 'th')
return suffix

def generate_chart_data(self):
categories = list(self.data.keys())
values = [self.data[cat]['change'] for cat in categories]
baselines = [self.data[cat]['baseline'] * 100 for cat in categories]
reforms = [self.data[cat]['reform'] * 100 for cat in categories]

# Generate hover texts with baseline, reform, and percentage change
hover_texts = [
f"This reform would {self._get_change_direction(val)} the percentage of {category.lower()} in poverty by {abs(val):.1f}% from {baseline:.1f}% to {reform:.1f}%"
for category, val, baseline, reform in zip(categories, values, baselines, reforms)
]

fig = go.Figure()

values_in_pct = values # Use percentage values
colors = [self._get_color(value) for value in values]

# Add bar chart with percentage values
fig.add_trace(go.Bar(
x=categories,
y=values_in_pct,
marker=dict(color=colors, line=dict(width=1)),
width=0.6,
text=[f"{abs(value):.1f}%" for value in values], # Display values as percentages
textposition='outside',
hovertemplate="<b>Category %{x}</b><br><br>%{customdata}<extra></extra>", # Hover shows category
customdata=hover_texts
))

# Update layout to reflect percentage values on y-axis
fig.update_layout(
yaxis=dict(
tickformat=",.1f%%",
ticksuffix = "%", # Format y-axis as percentages with one decimal place
title="Percentage Change in Poverty"
),
xaxis=dict(
title="Category"
),
hoverlabel=dict(
bgcolor="white",
font=dict(color="black", size=16)
),
title="Change in Poverty Percentage by Category"
)

format_fig(fig) # Keep the formatting logic from policyengine_core
return fig


# # Example data
# data = {
# 'Male': {
# 'Baseline': 0.18412623468617267,
# 'Reform': 0.18932591339284738,
# 'Change': 2.8
# },
# 'Female': {
# 'Baseline': 0.21377616483057263,
# 'Reform': 0.22004590877186603,
# 'Change': 2.9
# },
# 'All': {
# 'Baseline': 0.19913534734369268,
# 'Reform': 0.20487670454940832,
# 'Change': 2.9
# }
# }

# # Generate chart for all categories
# chart = OverallChart(data=data)
# fig = chart.generate_chart_data()
# fig.show()
Empty file.
107 changes: 107 additions & 0 deletions policyengine/charts/poverty/regular/by_age.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import plotly.graph_objects as go
from policyengine_core.charts.formatting import *

class RegularPovertyByAgeChart:
def __init__(self,country:str, data=None):
if data is None:
raise ValueError("Data must be provided")

self.data = data

def _get_color(self, value):
# All bars should be gray
return GRAY

def _get_change_direction(self, value):
if value > 0:
return "increase"
elif value < 0:
return "decrease"
else:
return "no change"

def ordinal_suffix(self, n):
"""Return the ordinal suffix for an integer."""
if 10 <= n % 100 <= 20:
suffix = 'th'
else:
suffix = {1: 'st', 2: 'nd', 3: 'rd'}.get(n % 10, 'th')
return suffix

def generate_chart_data(self):
categories = list(self.data.keys())
values = [self.data[cat]['change'] for cat in categories]
baselines = [self.data[cat]['baseline'] * 100 for cat in categories]
reforms = [self.data[cat]['reform'] * 100 for cat in categories]

# Generate hover texts with baseline, reform, and percentage change
hover_texts = [
f"This reform would {self._get_change_direction(val)} the percentage of {category.lower()} in poverty by {abs(val):.1f}% from {baseline:.1f}% to {reform:.1f}%"
for category, val, baseline, reform in zip(categories, values, baselines, reforms)
]

fig = go.Figure()

values_in_pct = values # Use percentage values
colors = [self._get_color(value) for value in values]

# Add bar chart with percentage values
fig.add_trace(go.Bar(
x=categories,
y=values_in_pct,
marker=dict(color=colors, line=dict(width=1)),
width=0.6,
text=[f"{abs(value):.1f}%" for value in values], # Display values as percentages
textposition='outside',
hovertemplate="<b>%{x}</b><br><br>%{customdata}<extra></extra>", # Hover shows category
customdata=hover_texts
))

# Update layout to reflect percentage values on y-axis
fig.update_layout(
yaxis=dict(
tickformat=",.1f%%", # Format y-axis as percentages with one decimal place
title="Percentage Change in Poverty"
),
xaxis=dict(
title="Category"
),
hoverlabel=dict(
bgcolor="white",
font=dict(color="black", size=16)
),
title="Change in Poverty Percentage by Category"
)

format_fig(fig) # Keep the formatting logic from policyengine_core
return fig


# # Example data
# data = {
# 'Child': {
# 'Baseline': 0.32427219591395395,
# 'Reform': 0.33392168532001054,
# 'Change': 3.0
# },
# 'Adult': {
# 'Baseline': 0.17427822561729264,
# 'Reform': 0.17757158627182623,
# 'Change': 1.9
# },
# 'Senior': {
# 'Baseline': 0.12817646500651358,
# 'Reform': 0.1370685860340031,
# 'Change': 6.9
# },
# 'All': {
# 'Baseline': 0.19913534734369268,
# 'Reform': 0.20487670454940832,
# 'Change': 2.9
# }
# }

# # Generate chart for all categories
# chart = OverallChart(data=data)
# fig = chart.generate_chart_data()
# fig.show()
Loading
Loading