liveBook · Manning

Transition matrix

As explained in Statistics Every Programmer Needs

A transition matrix is a matrix whose entries specify the probabilities of moving between states in a stochastic process.

A transition matrix stores the probabilities of moving between a finite set of states during one period. In Markov analysis, it turns a current distribution—such as customers across competing providers—into a forecast for the next period. This use assumes the next state depends on the current state, not the earlier path, and that transition probabilities remain constant over time. section 11.1 section 11.0

Write the matrix as P. Its entry Pᵢⱼ is the conditional probability of moving from current state i to next state j. Put starting states in rows and destination states in columns; Pᵢᵢ is the chance of staying put. Because the possible destinations are mutually exclusive and exhaustive, each row must sum to 1. A valid probability in the matrix lies between 0 and 1. section 11.2.2 section 11.3

>>> import numpy as np

>>> pi_0 = np.array([0.40, 0.35, 0.20, 0.05])

>>> P = np.array([
>>>     [0.85, 0.06, 0.07, 0.02],
>>>     [0.08, 0.80, 0.10, 0.02],
>>>     [0.10, 0.10, 0.75, 0.05],
>>>     [0.12, 0.10, 0.08, 0.70]
>>> ])

The NumPy listing defines a four-provider transition matrix alongside the starting market-share vector. Read its first row as an 85% chance of retaining a customer and respective 6%, 7%, and 2% chances of switching to the other providers. section 11.2.2

Represent the current distribution as a row vector π₀, then calculate the next distribution with π₁ = π₀P. Each destination’s result adds the contributions from every starting state. Reapply the same matrix for later periods: π₂ = π₁P = π₀P². In the provider example, [0.40, 0.35, 0.20, 0.05] becomes [0.394, 0.329, 0.217, 0.060] after one period. These are forecast shares, not individual customers’ certain destinations. section 11.2.2 section 11.5

Check longer-term behavior

For an engine with states running and not running, use P = [[0.90, 0.10], [0.20, 0.80]]. Starting at [1, 0], repeated NumPy dot products yield [0.90, 0.10] after one week and [0.83, 0.17] after two. By about period 10, the running probability is near two-thirds. An equilibrium distribution remains unchanged when multiplied by P; inspect successive vectors to see whether they stabilize rather than assuming they will. section 11.3 section 11.3.1

>>> pi_0 = np.array([1, 0])    #1

>>> P = np.array([
>>>     [0.90, 0.10],
>>>     [0.20, 0.80]
>>> ])     #2

>>> n_periods = 20     #3

>>> state_probabilities = [pi_0]     #4

>>> for _ in range(n_periods):
>>>     pi_next = np.dot(state_probabilities[-1], P)
>>>     state_probabilities.append(pi_next)     #5

>>> for i, pi in enumerate(state_probabilities):
>>>     print(f'Period {i} = {pi}')    #6
Period 0 = [1 0]
Period 1 = [0.9 0.1]
Period 2 = [0.83 0.17]
Period 3 = [0.781 0.219]
Period 4 = [0.7467 0.2533]
Period 5 = [0.72269 0.27731]
Period 6 = [0.705883 0.294117]
Period 7 = [0.6941181 0.3058819]
Period 8 = [0.68588267 0.31411733]
Period 9 = [0.68011787 0.31988213]
Period 10 = [0.67608251 0.32391749]
Period 11 = [0.67325776 0.32674224]
Period 12 = [0.67128043 0.32871957]
Period 13 = [0.6698963 0.3301037]
Period 14 = [0.66892741 0.33107259]
Period 15 = [0.66824919 0.33175081]
Period 16 = [0.66777443 0.33222557]
Period 17 = [0.6674421 0.3325579]
Period 18 = [0.66720947 0.33279053]
Period 19 = [0.66704663 0.33295337]
Period 20 = [0.66693264 0.33306736]

The loop stores each engine-state vector and prints 20 successive forecasts, making stabilization visible without random sampling. section 11.3.1

A terminal outcome changes the matrix’s structure. An absorbing state has probability 1 of remaining in itself and 0 of leaving; other rows can still lead into it. For delinquent accounts, separating absorbing from non-absorbing states permits calculation of eventual absorption probabilities using submatrices and a fundamental matrix. This is a different question from forecasting only the next period. section 11.4 section 11.4.3

>>> P = np.array([
>>>     [1, 0, 0, 0],
>>>     [0, 1, 0, 0],
>>>     [0.80, 0, 0.10, 0.10],
>>>     [0.30, 0.10, 0.30, 0.30]
>>> ])    #1

>>> I = np.array([
>>>     [1, 0],
>>>     [0, 1]
>>> ])     #2

>>> A = np.array([
>>>     [0.80, 0],
>>>     [0.30, 0.10]
>>> ])   #3

>>> B = np.array([
>>>     [0.10, 0.10],
>>>     [0.30, 0.30]
>>> ])     #4

>>> I_minus_B = I – B     #5
>>> F = np.linalg.inv(I_minus_B)     #6

>>> FA = np.dot(F, A)     #7

>>> print('The final matrix FA is:')
>>> print(FA)     #8

The final matrix FA is:
[[0.98333333 0.01666667]
 [0.85       0.15      ]]

The NumPy listing partitions a delinquency transition matrix and computes F = (I − B)⁻¹, then FA. Its rows give eventual probabilities of reaching each absorbing state from the two non-absorbing states. section 11.4.3

How Statistics Every Programmer Needs covers it

How deep it goes
Defines conditional matrix entries, works through vector multiplication and iteration, then partitions a matrix to calculate absorption probabilities.
Examples
Uses four-provider market shares, a running-or-not-running engine, and delinquency states with NumPy arrays and printed forecasts.
What it assumes
Introduces finite states and conditional transitions before using probability vectors, matrix multiplication, and NumPy arrays.
What you can do after
Apply it via NumPy to forecast successive state distributions, inspect stabilization, and calculate eventual absorbing-state probabilities.
How it connects
Connects Markov property, state probability vectors, matrix multiplication, equilibrium distributions, and absorbing states.

Also explained in

Compare how 2 books explain transition matrix →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Statistics Every Programmer Needs. The section links point to the parts of the book it draws on.