Quant Memo
Core

Cyclical Encoding for Time Features

Cyclical encoding represents a repeating time feature like hour-of-day or month as a pair of sine and cosine values, so a model correctly sees that 23:00 and 00:00 are adjacent rather than far apart.

Prerequisites: Ordinal and Label Encoding Pitfalls

Time-of-day, day-of-week, and month all wrap around: hour 23 is followed by hour 0, December is followed by January. Encoding them as plain integers (0–23 for hour, 1–12 for month) hides this wraparound — a model sees 23 and 0 as maximally far apart on the number line, even though 11pm and midnight are one hour apart in reality.

Cyclical encoding fixes this by mapping each time value onto a circle using a pair of sine and cosine features: xsin=sin(2πh/24)x_{sin} = \sin(2\pi \cdot h / 24) and xcos=cos(2πh/24)x_{cos} = \cos(2\pi \cdot h / 24) for an hour hh. In words: rescale the hour so a full day maps to one trip around a circle, then read off that point's horizontal and vertical coordinates. Now hour 23 and hour 0 land right next to each other on the circle, exactly as they should, and the model can learn smooth, continuous patterns across the wraparound point instead of a false discontinuity.

Any feature that wraps around (hour, weekday, month, wind direction) should be encoded as a sine/cosine pair, not a raw integer — otherwise the model treats the end of the cycle as maximally different from the start, when they're actually adjacent.

Worked example

Hour 23 encodes to (sin(2π23/24),cos(2π23/24))(0.26,0.97)(\sin(2\pi \cdot 23/24), \cos(2\pi \cdot 23/24)) \approx (-0.26, 0.97). Hour 0 encodes to (0,1)(0, 1). These two points sit close together on the unit circle, correctly reflecting that they're one hour apart — unlike raw integers 23 and 0, which sit 23 units apart on a number line despite being adjacent in real time.

Related concepts

Practice in interviews

Further reading

  • Kuhn & Johnson, Feature Engineering and Selection (ch. on categorical predictors)
ShareTwitterLinkedIn