Skip to content

Commit 7eb55d6

Browse files
committed
Change multi-plots to all show on the same figure rather than panels.
1 parent 0b33d64 commit 7eb55d6

2 files changed

Lines changed: 75 additions & 30 deletions

File tree

exploratory/osm_data_viz.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,19 +110,19 @@ def fig_save(
110110
fig_save(fig, stub = f"osm_changes_{TAG_KEY}_all")
111111

112112
# Create multi-panel plots for the top tags in each OSM category
113+
TOP_N_TYPES = 10
113114
for subtype in OSM_KEYS:
114115
fig = change_multiplot_create(
115116
observations = to_plot_df,
116117
col = subtype,
117-
top_n = 9,
118+
top_n = TOP_N_TYPES,
118119
no_change_col = 'no_change',
119120
change_col = 'change',
120121
final_observation_col = 'final_obs',
122+
title = f"Stability of the `{TAG_KEY}` tag over time by {subtype}",
123+
subtitle = f"Top {TOP_N_TYPES} {subtype} tags by number of observations",
124+
x_label = "Years since tag",
125+
y_label = "Proportion remaining unchanged",
121126
day_range = max_days,
122127
)
123-
fig_save(
124-
fig = fig,
125-
stub = f"osm_changes_{TAG_KEY}_{subtype}",
126-
height = 12,
127-
width = 12
128-
)
128+
fig_save(fig = fig, stub = f"osm_changes_{TAG_KEY}_{subtype}")

src/openpois/osm/change_plots.py

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ def change_plot_create(
104104
it was changed. For tags that were unchanged, this will be infinity.
105105
final_observation_col: Column name for the days elapsed from when the tag was
106106
added to when this data was downloaded.
107+
title: Title of the plot.
108+
subtitle: Subtitle of the plot.
109+
x_label: Label for the x-axis.
110+
y_label: Label for the y-axis.
107111
day_range: Maximum elapsed time period to plot, in days
108112
109113
Returns:
@@ -122,9 +126,9 @@ def change_plot_create(
122126
data = reshaped,
123127
mapping = gg.aes(x = 'year', ymin = 'ymin', ymax = 'ymax')
124128
) +
125-
gg.geom_ribbon(fill = 'blue', alpha = 0.4) +
126-
gg.geom_line(mapping = gg.aes(y = 'ymin'), color = 'black', alpha = 0.5) +
127-
gg.geom_line(mapping = gg.aes(y = 'ymax'), color = 'black', alpha = 0.5) +
129+
gg.geom_ribbon(fill = 'blue', alpha = 0.25) +
130+
gg.geom_line(mapping = gg.aes(y = 'ymin'), color = 'black', linetype = 'dashed') +
131+
gg.geom_line(mapping = gg.aes(y = 'ymax'), color = 'black') +
128132
gg.labs(
129133
title = title,
130134
subtitle = subtitle,
@@ -153,15 +157,31 @@ def change_multiplot_create(
153157
no_change_col: str = 'no_change',
154158
change_col: str = 'change',
155159
final_observation_col: str = 'final_obs',
160+
title: str = None,
161+
subtitle: str = None,
162+
x_label: str = '',
163+
y_label: str = '',
156164
day_range: int = 365*10,
157165
) -> gg.ggplot:
158166
"""
159167
Create a multi-panel change plot.
160168
161169
Args:
162-
col: Column name for the tag to plot.
170+
observations: DataFrame with observations. Each row is an iteration of a
171+
tag, with the three columns described below.
172+
col: Column name for the OSM grouping tag to plot.
163173
top_n: Number of tags to plot, ordered by number of observations.
164-
**kwargs: Keyword arguments for change_plot_create.
174+
no_change_col: Column name for the days elapsed from when the tag was added to
175+
when it was last confirmed (observed unchanged).
176+
change_col: Column name for the days elapsed from when the tag was added to when
177+
it was changed. For tags that were unchanged, this will be infinity.
178+
final_observation_col: Column name for the days elapsed from when the tag was
179+
added to when this data was downloaded.
180+
title: Title of the plot.
181+
subtitle: Subtitle of the plot.
182+
x_label: Label for the x-axis.
183+
y_label: Label for the y-axis.
184+
day_range: Maximum elapsed time period to plot, in days
165185
166186
Returns:
167187
ggplot object
@@ -171,24 +191,49 @@ def change_multiplot_create(
171191
obs_sub = observations.dropna(subset = [col])
172192
top_tags = obs_sub[col].value_counts().head(top_n)
173193
# Create a list of ggplot objects
174-
fig_list = []
194+
reshaped_list = []
175195
for tag, _ in top_tags.items():
176196
obs_sub_tag = obs_sub.query(f"{col} == @tag")
177-
fig = change_plot_create(
178-
observations = obs_sub_tag,
179-
title = tag.title(),
180-
subtitle = f"N = {obs_sub_tag.shape[0]}",
181-
no_change_col = no_change_col,
182-
change_col = change_col,
183-
final_observation_col = final_observation_col,
184-
day_range = day_range,
197+
reshaped_sub = (
198+
change_plot_reshape_data(
199+
observations = obs_sub_tag,
200+
no_change_col = no_change_col,
201+
change_col = change_col,
202+
final_observation_col = final_observation_col,
203+
day_range = day_range
204+
)
205+
.assign(
206+
group = tag.replace("_", " ").title() + f" (N = {obs_sub_tag.shape[0]})"
207+
)
185208
)
186-
fig_list.append(fig)
187-
# Compose the individual plots into a roughly square grid
188-
n_rows = np.ceil(np.sqrt(len(fig_list)))
189-
composed_rows = [
190-
reduce(lambda gg1, gg2: gg1 | gg2, row)
191-
for row in np.array_split(fig_list, n_rows)
192-
]
193-
composed_fig = reduce(lambda row1, row2: row1 / row2, composed_rows)
194-
return composed_fig
209+
reshaped_list.append(reshaped_sub)
210+
# Create a grouped change plot
211+
reshaped_full = pd.concat(reshaped_list)
212+
year_range = day_range / 365
213+
fig = (
214+
gg.ggplot(
215+
data = reshaped_full,
216+
mapping = gg.aes(x = 'year', color = 'group')
217+
) +
218+
gg.geom_line(mapping = gg.aes(y = 'ymin'), linetype = 'dashed') +
219+
gg.geom_line(mapping = gg.aes(y = 'ymax')) +
220+
gg.labs(
221+
title = title,
222+
subtitle = subtitle,
223+
x = x_label,
224+
y = y_label,
225+
color = col.replace("_", " ").title()
226+
) +
227+
gg.scale_y_continuous(
228+
limits = (0, 1.01),
229+
breaks = np.arange(0, 1.01, 0.25),
230+
labels = [f"{x*100:.0f}%" for x in np.arange(0, 1.01, 0.25)],
231+
) +
232+
gg.scale_x_continuous(
233+
limits = (0, year_range + 0.01),
234+
breaks = np.arange(year_range + 1),
235+
labels = [f"{x:.0f}" for x in np.arange(year_range + 1)],
236+
) +
237+
gg.theme_bw()
238+
)
239+
return fig

0 commit comments

Comments
 (0)