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

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.

naive.py
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)
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.