Compute the change between each element and the one before it in an ordered sequence. By hand, loop over indices: the first element has no predecessor so it gets None; the rest subtract the prior value. With pandas, Series.diff() computes all deltas in one call and returns NaN for the first row.

By hand

Track position with range(len(readings)). For index 0, append None; for all others, compute readings[i] - readings[i - 1] and append directly. The trace shows result growing one entry per iteration.

naive.py
Replay: real traced execution (multi-file project)
readings = [10, 13, 9, 15, 12, 18]
result = []
for i in range(len(readings)):
    if i == 0:
        result.append(None)
    else:
        result.append(readings[i] - readings[i - 1])
print('RESULT:', result)
  1. readings ← [10, 13, 9, 15, 12, 18]

    1readings = [10, 13, 9, 15, 12, 18]2result = []
    values this step[10, 13, 9, 15, 12, 18]readings
  2. result ← []

    1readings = [10, 13, 9, 15, 12, 18]2result = []3for i in range(len(readings)):
    values this step[]result
  3. i ← 0

    2result = []3for i in range(len(readings)):4    if i == 0:
    values this step0i
  4. if i == 0:

    3for i in range(len(readings)):4    if i == 0:5        result.append(None)
  5. result ← [None]

    4if i == 0:5    result.append(None)6else:
    values this step[] [None]result
  6. i ← 1

    2result = []3for i in range(len(readings)):4    if i == 0:
    values this step0 1i
  7. if i == 0:

    3for i in range(len(readings)):4    if i == 0:5        result.append(None)
  8. result ← [None, 3]

    6    else:7        result.append(readings[i] - readings[i - 1])8print('RESULT:', result)
    values this step[None] [None, 3]result
  9. i ← 2

    2result = []3for i in range(len(readings)):4    if i == 0:
    values this step1 2i
  10. if i == 0:

    3for i in range(len(readings)):4    if i == 0:5        result.append(None)
  11. result ← [None, 3, -4]

    6    else:7        result.append(readings[i] - readings[i - 1])8print('RESULT:', result)
    values this step[None, 3] [None, 3, -4]result
  12. i ← 3

    2result = []3for i in range(len(readings)):4    if i == 0:
    values this step2 3i
  13. if i == 0:

    3for i in range(len(readings)):4    if i == 0:5        result.append(None)
  14. result ← [None, 3, -4, 6]

    6    else:7        result.append(readings[i] - readings[i - 1])8print('RESULT:', result)
    values this step[None, 3, -4] [None, 3, -4, 6]result
  15. i ← 4

    2result = []3for i in range(len(readings)):4    if i == 0:
    values this step3 4i
  16. if i == 0:

    3for i in range(len(readings)):4    if i == 0:5        result.append(None)
  17. result ← [None, 3, -4, 6, -3]

    6    else:7        result.append(readings[i] - readings[i - 1])8print('RESULT:', result)
    values this step[None, 3, -4, 6] [None, 3, -4, 6, -3]result
  18. i ← 5

    2result = []3for i in range(len(readings)):4    if i == 0:
    values this step4 5i
  19. if i == 0:

    3for i in range(len(readings)):4    if i == 0:5        result.append(None)
  20. result ← [None, 3, -4, 6, -3, 6]

    6    else:7        result.append(readings[i] - readings[i - 1])8print('RESULT:', result)
    values this step[None, 3, -4, 6, -3] [None, 3, -4, 6, -3, 6]result
  21. for i in range(len(readings)):

    2result = []3for i in range(len(readings)):4    if i == 0:
  22. stdout ← RESULT: [None, 3, -4, 6, -3, 6]

    7        result.append(readings[i] - readings[i - 1])8print('RESULT:', result)
    values this stepRESULT: [None, 3, -4, 6, -3, 6]stdout

With pandas

df['x'].diff() subtracts each value from the previous one. The first row is NaN because there is no predecessor. The column is cast to float64 to accommodate NaN — the snapshot shows the raw floats, and the result line converts NaN → None and float → int for a clean comparison.

library.py
import math
import pandas as pd
from dalib.display import set_display
set_display()

readings = [10, 13, 9, 15, 12, 18]
df = pd.DataFrame({'x': readings})
d = df['x'].diff()
result = [int(v) if not math.isnan(v) else None for v in d.tolist()]
print('index:', d.index.tolist())
print('dtype:', d.dtype)
print('values raw:', d.tolist())
print('RESULT:', result)
index: [0, 1, 2, 3, 4, 5]
dtype: float64
values raw: [nan, 3.0, -4.0, 6.0, -3.0, 6.0]
RESULT: [None, 3, -4, 6, -3, 6]

Implementation notes

  • diff() defaults to periods=1 (one-step lag). Use periods=2 to compare each row with the one two rows back, or a negative value to look forward.
  • The float64 upcast happens because integer columns cannot hold NaN. Use math.isnan or pd.isna to detect and convert when comparing with a naive result that uses None.
  • For cumulative totals instead of deltas, use Series.cumsum().
  • Cross-reference: rolling-mean-small (this chapter) for a sliding-window aggregation over the same ordered series.