Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from pathlib import Path 

2from datetime import datetime 

3from datetime import timedelta 

4from typing import Union, List 

5 

6import plotly.io as pio 

7import plotly.graph_objects as go 

8import plotly.express as px 

9 

10from .location import Location 

11from .inflation import latest_cpi_df, CPI 

12from .dates import convert_date 

13 

14 

15pio.kaleido.scope.mathjax = None 

16 

17 

18def format_fig(fig): 

19 """Formats a plotly figure in a nicer way.""" 

20 fig.update_layout( 

21 width=1200, 

22 height=550, 

23 plot_bgcolor="white", 

24 title_font_color="black", 

25 font=dict( 

26 family="Linux Libertine Display O", 

27 size=18, 

28 color="black", 

29 ), 

30 ) 

31 gridcolor = "#dddddd" 

32 fig.update_xaxes(gridcolor=gridcolor) 

33 fig.update_yaxes(gridcolor=gridcolor) 

34 

35 fig.update_xaxes(showline=True, linewidth=1, linecolor='black', mirror=True, ticks='outside') 

36 fig.update_yaxes(showline=True, linewidth=1, linecolor='black', mirror=True, ticks='outside') 

37 

38 

39def write_fig(fig, output: Union[Path, str]): 

40 """ 

41 Writes a plotly figure to file. 

42 

43 Args: 

44 fig (plotly figure): The figure to be written 

45 output (Path): The path to the output file. 

46 If the directory does not exist, then it is created. 

47 Output can be PDF, SVG, JPG, PNG or HTML based on the extension. 

48 """ 

49 if not output: 

50 return 

51 

52 output = Path(output) 

53 output.parent.mkdir(exist_ok=True, parents=True) 

54 if output.suffix.lower() == ".html": 

55 fig.write_html(output) 

56 else: 

57 fig.write_image(output) 

58 

59 

60def plot_inflation_timeseries( 

61 compare_date: Union[datetime, str], 

62 start_date: Union[datetime, str, None] = None, 

63 end_date: Union[datetime, str, None] = None, 

64 value: Union[float, int] = 1, 

65 location: Union[Location, str] = Location.AUSTRALIA, 

66 **kwargs, 

67) -> go.Figure: 

68 """ 

69 Plots a time series of dollar values attached to a particular date's dollar value 

70 

71 Args: 

72 compare_date (datetime, str): Date to set relative value of the dollars too. 

73 start_date (datetime, str, optional): Date to set the beginning of the time series graph. Defaults to None, which starts in 1948. 

74 end_date (datetime, str, optional): Date to set the end of the time series graph too. Defaults to None, which will set the end date to the most recent quarter. 

75 value (float, int, optional): Value you in `compare_date` dollars to plot on the time series. Defaults to 1. 

76 location (Location, str, optional): The location for calculating the CPI. 

77 Options are 'Australia', 'Sydney', 'Melbourne', 'Brisbane', 'Adelaide', 'Perth', 'Hobart', 'Darwin', and 'Canberra'. 

78 Default is 'Australia'. 

79 kwargs: (Optional(dict)): additional parameters to feed into plotly.express.line function 

80 

81 Returns: 

82 plotly.graph_objects.Figure: line graph of inflated dollar values vs time 

83 """ 

84 cpi = CPI() 

85 

86 inflation = cpi.calc_inflation_timeseries( 

87 compare_date, start_date, end_date, value=value, location=location 

88 ).reset_index() 

89 new_col_name = f"Equivalent Dollar Value" 

90 if "title" not in kwargs: 

91 kwargs["title"] = f"The equivalent of ${value:.2f} from {str(compare_date)}" 

92 inflation.rename( 

93 columns={cpi.column_name(location): new_col_name}, 

94 inplace=True, 

95 ) 

96 fig = px.line(inflation, x="Date", y=new_col_name, **kwargs) 

97 format_fig(fig) 

98 return fig 

99 

100 

101def plot_cpi_timeseries( 

102 start_date: Union[datetime, str, None] = None, 

103 end_date: Union[datetime, str, None] = None, 

104 locations: List[Location] = None, 

105 title: str = None, 

106 **kwargs, 

107) -> go.Figure: 

108 """ 

109 Plots CPI vs time. 

110 

111 Args: 

112 start_date (datetime, str, optional): Date to set the beginning of the time series graph. Defaults to None, which starts in 1948. 

113 end_date (datetime, str, optional): Date to set the end of the time series graph too. Defaults to None, which will set the end date to the most recent quarter. 

114 locations (List[Location], optional): The location(s) for calculating the CPI. 

115 Options are 'Australia', 'Sydney', 'Melbourne', 'Brisbane', 'Adelaide', 'Perth', 'Hobart', 'Darwin', and 'Canberra'. 

116 Default is 'Australia'. 

117 title: (str, optional): The title of the figure. 

118 kwargs:: additional parameters to feed into plotly.express.line function. 

119 

120 Returns: 

121 plotly.graph_objects.Figure: plot of cpi vs time 

122 """ 

123 if not locations: 

124 locations = list(Location) 

125 

126 if start_date is not None: 

127 start_date = convert_date(start_date).item() 

128 if end_date is not None: 

129 end_date = convert_date(end_date).item() 

130 

131 df = latest_cpi_df() 

132 cpi = CPI() 

133 column_map = {cpi.column_name(location): str(location) for location in locations} 

134 df = df.rename(columns=column_map) 

135 df = df[column_map.values()] 

136 df = df[start_date:end_date].copy() 

137 df = df.reset_index() 

138 

139 fig = px.line(df, x="Date", y=list(column_map.values()), **kwargs) 

140 fig.update_layout( 

141 yaxis_title="CPI", 

142 legend_title="Location", 

143 ) 

144 

145 if title is None: 

146 location_name = locations[0] if len(locations) == 1 else "Australia" 

147 title = f"Consumer Price Index in {location_name} over time" 

148 

149 fig.update_layout(title=title) 

150 

151 if len(locations) == 1: 

152 fig.update_layout( 

153 showlegend=False, 

154 ) 

155 format_fig(fig) 

156 return fig 

157 

158 

159def plot_cpi_change( 

160 start_date: Union[datetime, str, None] = None, 

161 end_date: Union[datetime, str, None] = None, 

162 output: Union[Path, str, None] = None, 

163 locations: List[Location] = None, 

164 title: str = None, 

165 rba_target: bool = True, 

166) -> go.Figure: 

167 """ 

168 Produces a plot of the percentage change from corresponding quarter of previous year. 

169 

170 Args: 

171 start_date (datetime, str, optional): Date to set the beginning of the time series graph. Defaults to None, which starts in 1948. 

172 end_date (datetime, str, optional): Date to set the end of the time series graph too. Defaults to None, which will set the end date to the most recent quarter. 

173 output (Path, str, None): If given, then the plot is written to this path. 

174 

175 Returns: 

176 go.Figure: The resulting plotly figure. 

177 """ 

178 if not locations: 

179 locations = list(Location) 

180 

181 df = latest_cpi_df() 

182 df = df[start_date:end_date].copy() 

183 

184 if start_date is not None: 

185 start_date = convert_date(start_date).item() 

186 if end_date is not None: 

187 end_date = convert_date(end_date).item() 

188 

189 fig = go.Figure() 

190 for location in locations: 

191 fig.add_trace( 

192 go.Scatter( 

193 x=df.index, 

194 y=df[f'Percentage Change from Corresponding Quarter of Previous Year ; All groups CPI ; {location} ;'] 

195 / 100, 

196 name=str(location) if len(locations) > 1 else "CPI Change", 

197 line=dict(width=4.0 if location == Location.AUSTRALIA else 1.5), 

198 visible=1 if location == Location.AUSTRALIA else "legendonly", 

199 ) 

200 ) 

201 if rba_target: 

202 start_target = datetime(1992, 8, 17) 

203 fig.add_trace( 

204 go.Scatter( 

205 x=[start_target, df.index.max(), df.index.max(), start_target], 

206 y=[0.02, 0.02, 0.03, 0.03], 

207 fill='toself', 

208 fillcolor='rgba(0,176,246,0.2)', 

209 line_color='rgba(255,255,255,0)', 

210 name='RBA Target', 

211 showlegend=True, 

212 ) 

213 ) 

214 

215 if title is None: 

216 location_name = locations[0] if len(locations) == 1 else "Australia" 

217 title = f"Percentage change from corresponding quarter of previous year in {location_name}" 

218 

219 fig.update_layout( 

220 title=title, 

221 xaxis_title="Date", 

222 yaxis_title="Percentage Change", 

223 yaxis_tickformat=',.0%', 

224 xaxis_range=(df.index.min(), df.index.max() + timedelta(days=200)), 

225 ) 

226 fig.update_yaxes(zeroline=True, zerolinewidth=1, zerolinecolor='Black') 

227 

228 format_fig(fig) 

229 write_fig(fig, output) 

230 

231 return fig