Skip to content

Commit

Permalink
historic chart and filter form updated
Browse files Browse the repository at this point in the history
  • Loading branch information
amynickolls committed Apr 10, 2024
1 parent cff0c5e commit 2091595
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 20 deletions.
14 changes: 12 additions & 2 deletions dm_regional_app/charts.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,19 @@ def prediction_chart(prediction: Prediction):
def historic_chart(data: PopulationStats):
df_pp = data.stock.unstack().reset_index()
df_pp.columns = ["from", "date", "value"]
df = df_pp[["date", "value"]].groupby(by="date").sum().reset_index()

# visualise prediction using unstacked dataframe
fig = px.line(df_pp, y="value", x="date", color="from")
fig.update_layout(title="Prediction")
fig = px.line(
df,
y="value",
x="date",
labels={
"value": "Number of children",
"date": "Date",
},
)
fig.update_layout(title="Historic data")
fig.update_yaxes(rangemode="tozero")
fig_html = fig.to_html(full_html=False)
return fig_html
60 changes: 50 additions & 10 deletions dm_regional_app/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Column, Layout, Row, Submit
from django import forms
from django_select2 import forms as s2forms


class PredictFilter(forms.Form):
Expand All @@ -29,35 +30,58 @@ class HistoricDataFilter(forms.Form):
label="End Date",
required=True,
)
la = forms.ChoiceField(label="Local Authority", required=False, choices=[])
la = forms.MultipleChoiceField(
widget=s2forms.Select2MultipleWidget,
label="Local Authority",
required=False,
choices=[],
)
placement_types = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple,
widget=s2forms.Select2MultipleWidget,
label="Placement Type",
required=False,
choices=[],
)
age_bins = forms.MultipleChoiceField(
widget=s2forms.Select2MultipleWidget,
label="Age",
required=False,
choices=[],
)
uasc = forms.ChoiceField(
label="UASC",
required=False,
choices=[("all", "All"), (True, "UASC only"), (False, "Exclude UASC")],
initial="all",
)

def __init__(self, *args, **kwargs):
la_choices = kwargs.pop("la_choices")
placement_type_choices = kwargs.pop("placement_type_choices")
age_bin_choices = kwargs.pop("age_bin_choices")

super().__init__(*args, **kwargs)
self.fields["la"].choices = [("all", "All")] + [(la, la) for la in la_choices]
self.fields["la"].initial = "all"
self.fields["la"].choices = [(la, la) for la in la_choices]
self.fields["placement_types"].choices = [
(placement_type, placement_type)
for placement_type in placement_type_choices
]
self.fields["age_bins"].choices = [
(age_bin, age_bin) for age_bin in age_bin_choices
]

self.helper = FormHelper()
self.helper.layout = Layout(
Row(
Column("start_date", css_class="form-group col-md-6 mb-0"),
Column("end_date", css_class="form-group col-md-6 mb-0"),
Column("start_date", css_class="form-group col-md-3 mb-0"),
Column("end_date", css_class="form-group col-md-3 mb-0"),
css_class="form-row",
),
Row(
Column("la", css_class="form-group col-md-6 mb-0"),
Column("placement_types", css_class="form-group col-md-4 mb-0"),
Column("la", css_class="form-group col-md-3 mb-0"),
Column("placement_types", css_class="form-group col-md-3 mb-0"),
Column("age_bins", css_class="form-group col-md-3 mb-0"),
Column("uasc", css_class="form-group col-md-3 mb-0"),
css_class="form-row",
),
Submit("submit", "Filter"),
Expand All @@ -72,8 +96,9 @@ def filter_by_end_date(self, data: pd.DataFrame):
return data

def filter_by_la(self, data: pd.DataFrame):
if self.cleaned_data["la"] != "all":
data = data.loc[data.LA == self.cleaned_data["la"]]
if self.cleaned_data["la"] != []:
loc = data.LA.astype(str).isin(self.cleaned_data["la"])
data = data.loc[loc]
return data

def filter_by_placement_type(self, data: pd.DataFrame):
Expand All @@ -84,9 +109,24 @@ def filter_by_placement_type(self, data: pd.DataFrame):
data = data.loc[loc]
return data

def filter_by_age_bin(self, data: pd.DataFrame):
if self.cleaned_data["age_bins"] != []:
loc = data.age_bin.astype(str).isin(self.cleaned_data["age_bins"])
data = data.loc[loc]
return data

def filter_by_uasc(self, data: pd.DataFrame):
if self.cleaned_data["uasc"] == "True":
data = data.loc[data.UASC == True]
elif self.cleaned_data["uasc"] == "False":
data = data.loc[data.UASC == True]
return data

def apply_filters(self, data: pd.DataFrame):
data = self.filter_by_start_date(data)
data = self.filter_by_end_date(data)
data = self.filter_by_la(data)
data = self.filter_by_placement_type(data)
data = self.filter_by_age_bin(data)
data = self.filter_by_uasc(data)
return data
6 changes: 5 additions & 1 deletion dm_regional_app/management/commands/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ def handle(self, *args, **kwargs):
dc = DemandModellingDataContainer(datastore, config)
pop = PopulationStats(dc.enriched_view, config)

print(pop.stock)
data = dc.enriched_view
print(data.loc[data.UASC == True])

# print(pop.stock)
# print(dc.enriched_view)
15 changes: 12 additions & 3 deletions dm_regional_app/templates/dm_regional_app/views/historic.html
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
{% extends "dm_regional_app/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<br>
<h1>Viewing the SSDA903 data</h1>
<br>
<p>Explore the make-up of the care population as represented in the SSDA903 returns. You can filter the data to see the pattern of new care episodes over time across dimensions such as placement type, provider type, child age, child ethnicity, child gender, and whether the new placement followed a breakdown.</p>
<br>
<p><i>Select the period of data in the SSDA903 dataset you want to explore</i></p>
{{ form.media }}
<form method="POST">
{% csrf_token %}
{% crispy form %}
</form>
<br>
<div class="row">
<div class="col">
<h1>Total # of entry into care</h1>
<p>{{ entry_into_care_count }}</p>
<p><h1 class="display-2">{{ entry_into_care_count }}</h1></p>
</div>
<div class="col">
<h1>Total # of exiting care</h1>
<p>{{ exiting_care_count }}</p>
<p><h1 class="display-2">{{ exiting_care_count }}</h1></p>
</div>
</div>
<div class="alert alert-primary" role="alert">
{{chart|safe}}

</div>
<div class="d-flex bd-highlight mb-3">
<div class="ms-auto p-2 bd-highlight"><a class="btn btn-primary" href="{% url 'prediction' %}">Next</a></div>
</div>
{% endblock %}
2 changes: 2 additions & 0 deletions dm_regional_app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def historic_data(request):
request.POST,
la_choices=datacontainer.unique_las,
placement_type_choices=datacontainer.unique_placement_types,
age_bin_choices=datacontainer.unique_age_bins,
)
if form.is_valid():
data = form.apply_filters(datacontainer.enriched_view)
Expand All @@ -97,6 +98,7 @@ def historic_data(request):
},
la_choices=datacontainer.unique_las,
placement_type_choices=datacontainer.unique_placement_types,
age_bin_choices=datacontainer.unique_age_bins,
)
data = datacontainer.enriched_view

Expand Down
1 change: 1 addition & 0 deletions dm_regional_site/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"crispy_forms",
"crispy_bootstrap5",
"bootstrap_datepicker_plus",
"django_select2",
]

MIDDLEWARE = [
Expand Down
39 changes: 37 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ crispy-bootstrap5 = "^2024.2"
python-decouple = "^3.8"
faker = "^23.3.0"
django-bootstrap-datepicker-plus = "^5.0.5"
django-select2 = "^8.1.2"


[tool.poetry.group.dev.dependencies]
Expand Down
7 changes: 5 additions & 2 deletions ssda903/datacontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from functools import cached_property
from typing import Optional


import numpy as np
import pandas as pd

Expand Down Expand Up @@ -117,7 +116,7 @@ def combined_datasets(self) -> pd.DataFrame:
merged = merged.merge(uasc[["CHILD", "DUC"]], how="left", on="CHILD")

# create UASC flag if DECOM is less than DUC
merged["UASC"] = np.where(merged["DECOM"] < merged["DUC"], 1, 0)
merged["UASC"] = np.where(merged["DECOM"] < merged["DUC"], True, False)

return merged

Expand Down Expand Up @@ -203,6 +202,10 @@ def unique_las(self) -> pd.Series:
def unique_placement_types(self) -> pd.Series:
return self.enriched_view.placement_type.unique()

@cached_property
def unique_age_bins(self) -> pd.Series:
return self.enriched_view.age_bin.unique()

def _add_ages(self, combined: pd.DataFrame) -> pd.DataFrame:
"""
Calculates the age of the child at the start and end of the episode and adds them as columns
Expand Down

0 comments on commit 2091595

Please sign in to comment.