1
1
from typing import Dict , Optional
2
2
3
- from altair import Chart
3
+ from altair import Chart , Scale
4
4
import pandas as pd
5
5
import numpy as np
6
6
7
7
from ..constants import DATE_FORMAT
8
8
9
9
10
10
def build_admits_chart (
11
- * , alt , admits_floor_df : pd .DataFrame , max_y_axis : Optional [int ] = None
11
+ * , alt , admits_floor_df : pd .DataFrame , max_y_axis : Optional [int ] = None , use_log_scale : bool = False
12
12
) -> Chart :
13
- """Build admits chart."""
14
- y_scale = alt .Scale ()
15
- if max_y_axis is not None :
16
- y_scale .domain = (0 , max_y_axis )
13
+ """
14
+ This builds the "New Admissions" chart, projecting daily admissions over time.
17
15
18
- x = dict (shorthand = "date:T" , title = "Date" , axis = alt .Axis (format = (DATE_FORMAT )))
16
+ Args:
17
+ alt: Reference to Altair package.
18
+ admits_floor_df: Pandas data frame containing three columns: "admits_hospitalized", "admits_icu", and
19
+ "admits_ventilated".
20
+ max_y_axis: Optional maximum value for the Y axis of the chart.
21
+ use_log_scale: Set to true to use a logarithmic scale on the Y axis. Default is linear scale.
22
+
23
+ Returns: The newly created chart.
24
+
25
+ """
26
+
27
+ adjusted_admits_floor_df = __adjust_data_for_log_scale (admits_floor_df ) if use_log_scale else admits_floor_df
28
+ y_scale = __build_y_scale (alt , max_y_axis , use_log_scale )
29
+
30
+ x = dict (shorthand = "date:T" , title = "Date" , axis = alt .Axis (format = DATE_FORMAT ))
19
31
y = dict (shorthand = "value:Q" , title = "Daily admissions" , scale = y_scale )
20
32
color = "key:N"
21
33
tooltip = ["date:T" , alt .Tooltip ("value:Q" , format = ".0f" , title = "Admit" ), "key:N" ]
@@ -40,19 +52,31 @@ def build_admits_chart(
40
52
.mark_rule (color = "black" , opacity = 0.35 , size = 2 )
41
53
)
42
54
return (
43
- alt .layer (points , bar , data = admits_floor_df )
55
+ alt .layer (points , bar , data = adjusted_admits_floor_df )
44
56
.configure_legend (orient = "bottom" )
45
57
.interactive ()
46
58
)
47
59
48
60
49
61
def build_census_chart (
50
- * , alt , census_floor_df : pd .DataFrame , max_y_axis : Optional [int ] = None
62
+ * , alt , census_floor_df : pd .DataFrame , max_y_axis : Optional [int ] = None , use_log_scale : bool = False
51
63
) -> Chart :
52
- """Build census chart."""
53
- y_scale = alt .Scale ()
54
- if max_y_axis :
55
- y_scale .domain = (0 , max_y_axis )
64
+ """
65
+ This builds the "Admitted Patients" census chart, projecting total number of patients in the hospital over time.
66
+
67
+ Args:
68
+ alt: Reference to Altair package.
69
+ census_floor_df: Pandas data frame containing three columns: "census_hospitalized", "census_icu", and
70
+ "census_ventilated".
71
+ max_y_axis: Optional maximum value for the Y axis of the chart.
72
+ use_log_scale: Set to true to use a logarithmic scale on the Y axis. Default is linear scale.
73
+
74
+ Returns: The newly created chart.
75
+
76
+ """
77
+
78
+ adjusted_census_floor_df = __adjust_data_for_log_scale (census_floor_df ) if use_log_scale else census_floor_df
79
+ y_scale = __build_y_scale (alt , max_y_axis , use_log_scale )
56
80
57
81
x = dict (shorthand = "date:T" , title = "Date" , axis = alt .Axis (format = (DATE_FORMAT )))
58
82
y = dict (shorthand = "value:Q" , title = "Census" , scale = y_scale )
@@ -79,19 +103,31 @@ def build_census_chart(
79
103
.mark_rule (color = "black" , opacity = 0.35 , size = 2 )
80
104
)
81
105
return (
82
- alt .layer (points , bar , data = census_floor_df )
106
+ alt .layer (points , bar , data = adjusted_census_floor_df )
83
107
.configure_legend (orient = "bottom" )
84
108
.interactive ()
85
109
)
86
110
87
111
88
112
def build_sim_sir_w_date_chart (
89
- * , alt , sim_sir_w_date_floor_df : pd .DataFrame , max_y_axis : Optional [int ] = None
113
+ * , alt , sim_sir_w_date_floor_df : pd .DataFrame , max_y_axis : Optional [int ] = None , use_log_scale : bool = False
90
114
) -> Chart :
91
- """Build sim sir w date chart."""
92
- y_scale = alt .Scale ()
93
- if max_y_axis is not None :
94
- y_scale .domain = (0 , max_y_axis )
115
+ """
116
+ This builds the "Susceptible, Infected, and Recovered" chart, projecting the number of those individuals in the
117
+ hospital's region over time.
118
+
119
+ Args:
120
+ alt: Reference to the Altair package.
121
+ sim_sir_w_date_floor_df: A Pandas data frame with columns named "susceptible", "infected", and "recovered".
122
+ max_y_axis: Optional maximum value for the Y axis of the chart.
123
+ use_log_scale: Set to true to use a logarithmic scale on the Y axis. Default is linear scale.
124
+
125
+ Returns: The newly created chart.
126
+
127
+ """
128
+
129
+ adjusted_sim_sir_w_date_floor_df = __adjust_data_for_log_scale (sim_sir_w_date_floor_df ) if use_log_scale else sim_sir_w_date_floor_df
130
+ y_scale = __build_y_scale (alt , max_y_axis , use_log_scale )
95
131
96
132
x = dict (shorthand = "date:T" , title = "Date" , axis = alt .Axis (format = (DATE_FORMAT )))
97
133
y = dict (shorthand = "value:Q" , title = "Count" , scale = y_scale )
@@ -118,7 +154,7 @@ def build_sim_sir_w_date_chart(
118
154
.mark_rule (color = "black" , opacity = 0.35 , size = 2 )
119
155
)
120
156
return (
121
- alt .layer (points , bar , data = sim_sir_w_date_floor_df )
157
+ alt .layer (points , bar , data = adjusted_sim_sir_w_date_floor_df )
122
158
.configure_legend (orient = "bottom" )
123
159
.interactive ()
124
160
)
@@ -131,3 +167,37 @@ def build_table(
131
167
table_df .date = table_df .date .dt .strftime (DATE_FORMAT )
132
168
table_df .rename (labels )
133
169
return table_df
170
+
171
+
172
+ def __adjust_data_for_log_scale (dataframe : pd .DataFrame ) -> pd .DataFrame :
173
+ """
174
+ This will clean and adjust some of the data so that Altair can plot it using a logarithmic scale. Altair does not
175
+ allow zero values on the Y axis when plotting with a logarithmic scale, as log(0) is undefined.
176
+
177
+ Args:
178
+ dataframe: The data to plot on the chart.
179
+
180
+ Returns: A new data frame with the appropriate adjustments for plotting on a log scale.
181
+
182
+ """
183
+ return dataframe .replace (0 , float ('nan' )) # We use NaN so that the values will not appear at all on the chart.
184
+
185
+
186
+ def __build_y_scale (alt , max_y_axis : Optional [int ] = None , use_log_scale : bool = False ) -> Scale :
187
+ """
188
+ Creates the Y axis of the chart, taking into account some of the configuration parameters set by the user.
189
+
190
+ Args:
191
+ alt: Reference to Altair package.
192
+ max_y_axis: The maximum value of the Y axis. This is optional.
193
+ use_log_scale: Whether to use a logarithmic scale instead of a linear scale.
194
+
195
+ Returns: A newly created Scale instance.
196
+
197
+ """
198
+ scale_type = 'log' if use_log_scale else 'linear'
199
+ y_scale = alt .Scale (type = scale_type )
200
+ if max_y_axis is not None :
201
+ y_scale .domain = (0 , max_y_axis )
202
+
203
+ return y_scale
0 commit comments