Dates and Ordered Data
Diff Previous Row
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.
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)
readings ← [10, 13, 9, 15, 12, 18]
1readings = [10, 13, 9, 15, 12, 18]2result = []values this step[10, 13, 9, 15, 12, 18]readingsresult ← []
1readings = [10, 13, 9, 15, 12, 18]2result = []3for i in range(len(readings)):values this step[]resulti ← 0
2result = []3for i in range(len(readings)):4 if i == 0:values this step0iif i == 0:
3for i in range(len(readings)):4 if i == 0:5 result.append(None)result ← [None]
4if i == 0:5 result.append(None)6else:values this step[] → [None]resulti ← 1
2result = []3for i in range(len(readings)):4 if i == 0:values this step0 → 1iif i == 0:
3for i in range(len(readings)):4 if i == 0:5 result.append(None)result ← [None, 3]
6 else:7 result.append(readings[i] - readings[i - 1])8print('RESULT:', result)values this step[None] → [None, 3]resulti ← 2
2result = []3for i in range(len(readings)):4 if i == 0:values this step1 → 2iif i == 0:
3for i in range(len(readings)):4 if i == 0:5 result.append(None)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]resulti ← 3
2result = []3for i in range(len(readings)):4 if i == 0:values this step2 → 3iif i == 0:
3for i in range(len(readings)):4 if i == 0:5 result.append(None)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]resulti ← 4
2result = []3for i in range(len(readings)):4 if i == 0:values this step3 → 4iif i == 0:
3for i in range(len(readings)):4 if i == 0:5 result.append(None)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]resulti ← 5
2result = []3for i in range(len(readings)):4 if i == 0:values this step4 → 5iif i == 0:
3for i in range(len(readings)):4 if i == 0:5 result.append(None)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]resultfor i in range(len(readings)):
2result = []3for i in range(len(readings)):4 if i == 0: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.
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 toperiods=1(one-step lag). Useperiods=2to compare each row with the one two rows back, or a negative value to look forward.- The
float64upcast happens because integer columns cannot holdNaN. Usemath.isnanorpd.isnato detect and convert when comparing with a naive result that usesNone. - 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.