Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
Sensors report every minute, and occasionally a reading is dropped in transit. The dashboard looks broken when a single minute is empty, so short gaps are filled with the previous reading. What must not happen is a sensor going offline for an hour and the dashboard showing a flat, confident line the whole time.
Write forward_fill(rows, key_field, order_field, fill_fields, limit).
Function to write
forward_fill(rows: list[dict], key_field: str, order_field: str, fill_fields: list[str], limit: int) -> list[dict]Copies of the rows in key and order sequence, with short gaps filled from the previous value.
How to approach it
Key the last-value and the run-length state by both the group and the field.
Sample cases
+ 2 held back until you submit
a sensor that went quiet
Three consecutive gaps against a limit of two, with a second sensor interleaved in the feed.
Input
Argument 1
| sensor | at | temp | status |
|---|---|---|---|
| s2 | 09:00 | 20 | ok |
| s1 | 09:00 | 10 | ok |
| s1 | 09:01 | None | None |
| s1 | 09:02 | None | None |
| s1 | 09:03 | None | None |
| s1 | 09:04 | 14 | ok |
| s2 | 09:01 | None | None |
Argument 2
'sensor'Argument 3
'at'Argument 4
[
'temp',
'status'
]Argument 5
2Returns
| sensor | at | temp | status |
|---|---|---|---|
| s1 | 09:00 | 10 | ok |
| s1 | 09:01 | 10 | ok |
| s1 | 09:02 | 10 | ok |
| s1 | 09:03 | None | None |
| s1 | 09:04 | 14 | ok |
| s2 | 09:00 | 20 | ok |
| s2 | 09:01 | 20 | ok |
no rows
Nothing to fill returns an empty list rather than a row of carried values.
Input
Argument 1
[] (empty list)
Argument 2
'sensor'Argument 3
'at'Argument 4
[
'temp'
]Argument 5
2Returns
[] (empty list)
no carrying allowed
A limit of zero leaves every gap as it was, which is how you turn the feature off.
Input
Argument 1
| sensor | at | temp | status |
|---|---|---|---|
| s2 | 09:00 | 20 | ok |
| s1 | 09:00 | 10 | ok |
| s1 | 09:01 | None | None |
| s1 | 09:02 | None | None |
| s1 | 09:03 | None | None |
| s1 | 09:04 | 14 | ok |
| s2 | 09:01 | None | None |
Argument 2
'sensor'Argument 3
'at'Argument 4
[
'temp'
]Argument 5
0Returns
| sensor | at | temp | status |
|---|---|---|---|
| s1 | 09:00 | 10 | ok |
| s1 | 09:01 | None | None |
| s1 | 09:02 | None | None |
| s1 | 09:03 | None | None |
| s1 | 09:04 | 14 | ok |
| s2 | 09:00 | 20 | ok |
| s2 | 09:01 | None | None |
Constraints
order_field, ascending, compared as text, and return the rows in that order.None. Carry the last known value into it.limit consecutive gaps. The gap after that stays empty, and so does every one after it until a real value arrives.fill_fields has its own budget. One field going quiet does not consume another's.Worked example
Sensor s1 reports 10.0 at 09:00 and then nothing for three minutes. With a limit of 2, the 09:01 and 09:02 rows carry 10.0 and the 09:03 row stays empty — so the chart shows a short flat segment and then an honest hole. Filling all three would draw a straight line from 10.0 to the 14.0 at 09:04 and hide the fact that the sensor was silent.
Sensor s2 sits between s1's rows in the feed. A single last value variable carries s1's 10.0 into s2's empty 09:01 row, which is not a smoothing decision at all — it is one sensor's reading attributed to another. The state has to be keyed by sensor and by field.
What this tests
Per-group, per-field state with a budget that resets, and the judgement that imputation must be bounded. An unbounded forward fill is not a fix for missing data; it is a way of making missing data invisible.
forward_fill(rows: list[dict], key_field: str, order_field: str, fill_fields: list[str], limit: int) -> list[dict]Submit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.