Skip to content

Commit 1f5febb

Browse files
committed
Adaptive generator layout and better missingness handling
1 parent 8066e8f commit 1f5febb

File tree

1 file changed

+62
-36
lines changed

1 file changed

+62
-36
lines changed

d1-dossier-plant.py

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ def pretty_plant_name(row):
3535
return f"{row.plant_name_eia} (id={row.plant_id_eia})"
3636

3737

38+
@app.function
39+
def pretty_value_counts(series):
40+
return ", ".join(f"{k} ({v})" for k,v in series.value_counts().to_dict().items())
41+
42+
3843
@app.cell
3944
def _(mo, pudl):
4045
with mo.status.progress_bar(total=4, title="Loading data", subtitle="out_eia__yearly_plants", remove_on_exit=True) as bar:
@@ -105,7 +110,7 @@ def _(mo, out_eia__yearly_plants, selected_plant):
105110
str(i): i
106111
for i in available_years
107112
},
108-
label="Data as of:",
113+
label="Report date:",
109114
value=str(available_years.iloc[0])
110115
)
111116
return (selected_year,)
@@ -129,11 +134,13 @@ def _(
129134
this_plant = this_plant.rename(pretty_plant_name(this_plant))
130135

131136
this_plant__monthly_generation_fuel_combined = out_eia923__monthly_generation_fuel_combined.loc[
132-
out_eia923__monthly_generation_fuel_combined.plant_id_eia == selected_plant.value
137+
(out_eia923__monthly_generation_fuel_combined.plant_id_eia == selected_plant.value) &
138+
(out_eia923__monthly_generation_fuel_combined.report_date.dt.year <= selected_year.value.year)
133139
]
134140

135141
this_plant__monthly_generation = out_eia923__monthly_generation.loc[
136-
(out_eia923__monthly_generation.plant_id_eia == selected_plant.value)
142+
(out_eia923__monthly_generation.plant_id_eia == selected_plant.value) &
143+
(out_eia923__monthly_generation.report_date.dt.year <= selected_year.value.year)
137144
]
138145

139146
this_plant__generators = out_eia__yearly_generators.loc[
@@ -149,7 +156,8 @@ def _(
149156
this_plant__summary = pd.Series({
150157
"fuel_types": ", ".join(this_plant__monthly_generation_fuel_combined.fuel_type_code_pudl.unique()),
151158
"generators": this_plant__generators.shape[0],
152-
"technologies": ", ".join(this_plant__generators.technology_description.dropna().drop_duplicates())
159+
"status": pretty_value_counts(this_plant__generators.operational_status),
160+
"technologies": pretty_value_counts(this_plant__generators.technology_description.dropna())
153161
}, name=this_plant.name)
154162

155163
mo.vstack([
@@ -201,7 +209,7 @@ def _(alt, mo, this_plant, this_plant__monthly_generation_fuel_combined):
201209
alt.Y("net_generation_mwh", aggregate="sum").title("Net Generation (MWh)"),
202210
).properties(title=f"Total: {this_plant.name}, {this_plant['city']}, {this_plant['state']}")
203211
mo.output.append(mo.ui.altair_chart(plant_netgen_chart))
204-
212+
205213
plant_netgen_bysource_chart = alt.Chart(this_plant__monthly_generation_fuel_combined).mark_line().encode(
206214
alt.X("report_date").title("Report date"),
207215
alt.Y("net_generation_mwh", aggregate="sum").title("Net Generation (MWh)"),
@@ -244,7 +252,8 @@ def _(mo, this_plant__generators):
244252
filters = {}
245253
only_option = set()
246254
for k,v in nonmeasurement_counts.to_dict().items():
247-
available = this_plant__generators[k].value_counts(dropna=False).index
255+
available = this_plant__generators[k].value_counts(dropna=False)
256+
available = available.loc[available>0].index
248257
if available.shape[0]==1:
249258
only_option.add(k)
250259
filters[k] = mo.ui.multiselect(options={str(x): x for x in available}, value=[str(available[0])] if k in only_option else None)
@@ -254,31 +263,40 @@ def _(mo, this_plant__generators):
254263

255264
@app.cell
256265
def _(filters, functools, itertools, mo, only_option, this_plant__generators):
257-
mo.output.append(
258-
mo.hstack([
259-
mo.vstack([
260-
mo.hstack([mo.md(f[0]).right(), f[1]], widths=[1.1,1]).style({"color":"#bbbbbb"} if f[0] in only_option else {})
261-
for f in row if f
262-
])
263-
for row in itertools.zip_longest(*itertools.batched(filters.items(), 3))
264-
], widths=[0.65,1,1])
265-
)
266-
selected__generators = this_plant__generators[
267-
functools.reduce(
268-
lambda accum, update: accum & update,
269-
[
270-
this_plant__generators[k].isin(v.value)
271-
for k,v in filters.items() if v.value
272-
]
266+
if len(filters)==0:
267+
mo.output.append(mo.md("No other information about generators for this plant.").style({"background":"#fee"}))
268+
else:
269+
import math
270+
max_column = max((len(k) + max(len(vk) for vk in v.options)) for k,v in filters.items())
271+
max_label = max(len(k) for k,v in filters.items())
272+
max_input = max(max(len(vk) for vk in v.options) for v in filters.values())
273+
columns = math.ceil(80/max_column)
274+
275+
mo.output.append(
276+
mo.hstack([
277+
mo.vstack([
278+
mo.hstack([mo.md(f[0]).right(), f[1]], widths=[max_label/max_input, 1]).style({"color":"#bbbbbb"} if f[0] in only_option else {})
279+
for f in row if f
280+
])
281+
for row in itertools.batched(filters.items(), math.ceil(len(filters)/columns))
282+
], widths="equal")
273283
)
274-
]
275-
mo.output.append(mo.hstack([
276-
mo.md(
277-
"All" if selected__generators.shape[0] == this_plant__generators.shape[0]
278-
else f"{selected__generators.shape[0]} of"
279-
),
280-
mo.md(f"{this_plant__generators.shape[0]} generators selected")
281-
], justify="start").style(background="#eee"))
284+
selected__generators = this_plant__generators[
285+
functools.reduce(
286+
lambda accum, update: accum & update,
287+
[
288+
this_plant__generators[k].isin(v.value)
289+
for k,v in filters.items() if v.value
290+
]
291+
)
292+
]
293+
mo.output.append(mo.hstack([
294+
mo.md(
295+
"All" if selected__generators.shape[0] == this_plant__generators.shape[0]
296+
else f"{selected__generators.shape[0]} of"
297+
),
298+
mo.md(f"{this_plant__generators.shape[0]} generators selected")
299+
], justify="start").style(background="#eee"))
282300
return (selected__generators,)
283301

284302

@@ -297,18 +315,26 @@ def _(this_plant__generators):
297315
]+[f"energy_source_code_{i}" for i in range(1,7)]
298316
ignore_columns = [
299317
"operational_status_code",
300-
301318
]
302319
remaining_columns = ["generator_id"] + sorted(set(this_plant__generators.columns) - set(ops_columns+nrg_columns))
303320
return nrg_columns, ops_columns, remaining_columns
304321

305322

306323
@app.cell
307-
def _(mo, nrg_columns, ops_columns, remaining_columns, selected__generators):
308-
mo.output.append(mo.ui.table(
309-
selected__generators[
310-
ops_columns+nrg_columns[1:]+remaining_columns[1:]
311-
].set_index("generator_id").T.dropna(thresh=1)))
324+
def _(
325+
filters,
326+
mo,
327+
nrg_columns,
328+
ops_columns,
329+
remaining_columns,
330+
selected__generators,
331+
):
332+
if filters.value:
333+
mo.output.append(mo.ui.table(
334+
selected__generators[
335+
ops_columns+nrg_columns[1:]+remaining_columns[1:]
336+
].set_index("generator_id").T.dropna(thresh=1)
337+
))
312338
return
313339

314340

0 commit comments

Comments
 (0)