Writing Data
The same bracket syntax used for reading also supports writes. Assignments are sent to PowerWorld immediately — there’s no intermediate buffer or commit step. This makes it straightforward to script parameter sweeps, contingency setups, or any other case modification workflow.
from esapp import PowerWorld
from esapp.components import *
pw = PowerWorld("path/to/case.pwb")
Write Patterns
There are four write patterns, each useful in different situations:
Syntax |
Behavior |
|---|---|
|
Broadcast a scalar to every object |
|
Set per-element values (length must match) |
|
Broadcast to multiple fields at once |
|
Bulk update from a DataFrame (must include key columns) |
Let’s look at each one.
Scalar broadcast applies a single value to every object of that type. This is useful for resetting all generators to the same output, for example.
In [2]:
pw[Gen, "GenMW"] = 100.0
Per-element values - a list or array whose length matches the number of objects sets each one individually.
In [3]:
pw[Gen, "GenMW"] = np.linspace(50, 200, len(pw[Gen]))
Multiple fields - pass a list of field names and a matching list of values to set several columns at once.
In [4]:
pw[Gen, ["GenMW", "GenStatus"]] = [100.0, "Closed"]
DataFrame Updates
For targeted updates to specific objects, build a DataFrame that includes the primary-key columns and the fields you want to change. Only the rows present in the DataFrame are modified - everything else stays untouched.
In [5]:
updates = pd.DataFrame({
"BusNum": pw[Bus]["BusNum"].head(3),
"BusPUVolt": [1.02, 1.01, 0.99]
})
pw[Bus] = updates
Read-Modify-Write
A common workflow is to read existing values, transform them in pandas, and write the result back. This is the natural way to do things like scaling loads, adjusting setpoints, or applying any vectorized transformation. Here we scale all loads by 10%.
In [6]:
loads = pw[Load, ["LoadMW", "LoadMVR"]]
loads["LoadMW"] *= 1.10
loads["LoadMVR"] *= 1.10
pw[Load] = loads