Stats for

Other Specialized Models

Markov Models

A Markov model estimates how people move between states over time.

A Markov model takes a categorical state recorded for the same people on repeated occasions and estimates how likely they are to move between states, and where they settle in the long run.

Example

After a low-mood day, how likely is the next day to be low too, and where do people's moods settle over time? One hundred adults rated their mood every evening for two weeks. Each day was classified as low, neutral or good, giving 1,300 moves from one day to the next.

Same People, Many Occasions + One Categorical State + Day-to-Day Transitions → Markov Models
Tests
Transition probabilities between states
Observations
Related
Parametric
Yes
Headline Statistic
p_{ij}
Effect Size
Cramér's V
Groups
1

The Basics

When to Use It

Use it when the same people are sorted into one of a few categories (states) on many equally spaced occasions, and you want to describe how they move between states: how sticky each state is, which moves are common, and where people tend to end up. It sits between description and modeling: the estimates are the point, and the test is a starting check. For example:

  • After a low-mood day, how likely is the next day to be low too, and where do people's moods settle over time?
  • Among adults trying to quit, how often do people move between smoking, having quit recently (under 6 months) and having quit for longer, from one survey wave to the next?
  • In a classroom observation study, how often does a child who is off task in one five-minute interval get back on task in the next?

Vocabulary You Need

Definition State

One of a fixed set of categories that each person is sorted into at every occasion, such as low, neutral or good mood on a given day, or smoking, quit recently (under 6 months) and quit for longer at each wave. The states must cover every possibility and not overlap, so at each occasion a person is in exactly one. A Markov model describes how people move between states from one occasion to the next. Glossary →

Definition Transition Matrix (P)

The transition probabilities laid out as a square table: row i holds the chances of moving from state i to each state at the next occasion, so every row adds up to 1. The diagonal holds the chances of staying in the same state. Multiplying the matrix by itself gives the chances two occasions ahead, and raising it to the nth power gives them n occasions ahead. Glossary →

Definition Stationary Distribution (\pi)

The long-run share of occasions spent in each state implied by a transition matrix: the set of proportions π that the matrix leaves unchanged, so that π P = π. If a population were spread across the states in these proportions, it would stay that way from one occasion to the next, even though individuals keep moving. For a chain in which every state can eventually be reached from every other and that doesn't cycle in a fixed rhythm (irreducible and aperiodic; an irreducible chain in which some state can stay put is aperiodic), the chances n steps ahead approach π as n grows, whatever the starting state. Glossary →

Assumptions

1. Markov Property Tomorrow's state depends on today's state, not on the days before it.
What It Means
Once you know which state someone is in now, knowing where they were earlier adds nothing to predicting where they'll be next. This is the “first-order” part of a first-order Markov chain. It doesn't say the past is irrelevant, only that its influence is carried entirely by the present state.
Applies To
Observations
How to Check
Fit a second-order model, in which the chance of each state tomorrow depends on both today and yesterday, and compare it with the first-order model using a likelihood ratio test (Anderson & Goodman, 1957). Also look at the three-way table of yesterday × today × tomorrow: within each of today's states, tomorrow's split should look the same whatever yesterday was.
How Much It Matters
It decides whether the matrix's predictions can be trusted. If yesterday matters beyond today, predictions two or more days ahead (and how long runs last) are off, though the one-day probabilities still describe the pooled data. The long-run shares still match the observed ones if those shares don't drift over the study. In the mood-diary study the second-order check didn't detect a problem, G²(12) = 12.95, p = .372.

If It's Violated

  • Alternative Test Fit a second-order chain, which treats each pair of consecutive days as a state. It needs many more transitions: with 3 states it estimates 18 free probabilities instead of 6.
  • Alternative Test Multinomial Regression. Predict tomorrow's state from today's and yesterday's (and anything else) in a multinomial regression, which gives the same likelihood ratio tests as the tables here.
2. Time Homogeneity The chances of moving between states stay the same across the study.
What It Means
The transition probabilities are the same at every occasion: the chance of going from a low day to a good day is the same in the first week as in the second. Often called stationarity, which isn't the same as the stationary distribution: this is about the matrix staying the same over time, not about the shares of people in each state. It's what lets one transition matrix describe the whole study and be raised to powers for predictions.
Applies To
Observations
How to Check
Estimate the transition matrix separately for different stretches of the study (each occasion, or grouped periods such as weeks) and compare them with the single pooled matrix using a likelihood ratio test (Anderson & Goodman, 1957). Think about the design too: holidays, treatment starting partway through, or people getting used to the diary can all change the transitions.
How Much It Matters
Moderate. If transitions change over the study, the pooled matrix averages over the change, and powers of it predict the wrong thing. In the mood-diary study the first and second weeks' matrices didn't differ detectably, G²(6) = 3.67, p = .721.

If It's Violated

  • Alternative Test Estimate a separate matrix for each period (or occasion) and report them side by side.
  • Alternative Test Multinomial Regression. Add time, or the period, as a predictor of tomorrow's state alongside today's.
3. Same Transition Probabilities for Everyone Everyone you pooled moves between states in the same way.
What It Means
Pooling everyone's transitions into one table treats all people as following the same transition matrix. If people differ, say some have very sticky moods and others very changeable ones, the pooled matrix is an average that may describe nobody well, and the standard errors, which treat every transition as a fresh piece of information, come out too small. The pooled table can even show persistence that no one has: if some people are low more often than others, a low day predicts another low day even when no one's mood carries over.
Applies To
Observations
How to Check
Compare transition matrices across groups you care about (men and women, patients and controls) with a likelihood ratio test. Don't eyeball each person's own transition proportions: from a dozen or so transitions they're mostly noise. Instead, model tomorrow's state with a random intercept for each person (a multilevel logistic or multinomial regression; in R, for example, lme4's glmer(I(next_mood == "low") ~ mood + (1 | participant), family = binomial)). A person variance well above zero means people differ in how often they're in each state, and then the pooled persistence mixes carry-over with differences between people. In the simulated mood-diary data that variance is essentially zero. With intensive diary data, a mixed Markov model estimates the spread in the transitions themselves (de Haan-Rietdijk et al., 2017).
How Much It Matters
Often a lot, and it's the assumption the pooled table can't check by itself. Pooling people who differ averages their matrices and makes the standard errors too small. It can also create persistence: if some people are low more often than others, a low day predicts another low day even when no one's mood carries over. For the same reason the pooled data can look non-Markov: yesterday seems to predict tomorrow because it tells you what kind of person you're looking at. The mood-diary data are simulated from one shared matrix, so they meet it by construction; real diaries rarely do.

If It's Violated

  • Alternative Test A mixed (random-effects) Markov model lets each person have their own transition probabilities around a population average (de Haan-Rietdijk et al., 2017).
  • Alternative Test Multilevel Logistic Regression. A multilevel logistic or multinomial model of tomorrow's state, with random effects for people, is the regression version of the same idea.
  • Design Change Estimate separate matrices for groups you expect to differ, and test whether they're the same.
4. Independent Observations The people (or other units) in your study don't influence each other.
What It Means
Each person's data comes from a separate, unconnected source, so knowing one person's scores tells you nothing about anyone else's. In designs that measure people more than once, their own scores are meant to be related; it's different people who must be independent. Methods built for clustered data, such as multilevel models and GEE, also allow members of the same group to be related, as long as the analysis names the grouping; then it's the groups that must be independent.
Applies To
Observations
How to Check
By design, not by a test. Did each person contribute their own data, with no clusters such as roommates, couples, therapy groups or classrooms whose members influence each other? If there are clusters, does the analysis model every one of them?
How Much It Matters
A lot. The model already allows each person's days to be related; what it needs is that different people don't influence each other. Couples, roommates or members of one therapy group who share bad days make the transitions less informative than they look, so the intervals come out too narrow.

If It's Violated

  • Design Change Recruit people who don't live or work together, or analyze one person per cluster.
  • Alternative Test Multilevel Logistic Regression. Model the clusters with a multilevel model of tomorrow's state.

Limitations

This Is Not Your Test If…

What It Doesn't Tell You

  • Why. The matrix describes how moods follow one another, not what moves them. A low day might be followed by another because of rumination, a bad week at work or poor sleep, or simply because some people are low more often than others, and the pooled matrix can't tell which.
  • Whether it matters. A significant G² only says today's mood predicts tomorrow's in the pooled data, which is true of almost any daily measure. It can come from moods carrying over or from stable differences between people. Whether low stretches of about two and a half days are worth intervening on is a clinical judgment.
  • Anyone in particular. The pooled matrix is an average over 100 people. It says what a typical day looks like across the sample, not how any one person's moods behave; people with very sticky low moods are hidden in it.
  • Who else. The result describes adults like these over two particular weeks, with moods sorted into three categories. Cut points for "low" and "good," or a different season, could change the probabilities.

Common Mistakes

  • Don'tCount each person's daily states as separate people in a chi-square test comparing days.

    InsteadTabulate moves from one occasion to the next; the Markov model builds in that each person's days are linked.

  • Don'tReport the pooled transition matrix as though it describes each person.

    InsteadSay it's a population average, and check or model how much people differ before predicting for individuals.

  • Don'tRead the Markov vs independence test as the main finding.

    InsteadReport the transition probabilities with intervals first. Almost any repeated measure is related from one day to the next.

  • Don'tRaise the matrix to high powers without checking the Markov property and time homogeneity.

    InsteadTest second order and time homogeneity first, and compare predicted with observed shares a few steps ahead.

  • Don'tUse a Markov chain when states are fuzzy or measured with a lot of error.

    InsteadUse a hidden (latent) Markov model, which separates true switching from misclassification.

  • Don'tRead a bigger χ² as a stronger effect.

    InsteadReport an effect size suited to the design, such as Cramér's V, an odds ratio or a model's coefficients. χ² grows with sample size even when the effect doesn't.

  • Don'tRead a p-value as the chance that the null hypothesis is true.

    InsteadRead it as: if the null were true, how often data at least this extreme would turn up.

Result Decoder

Significance and Effect Size Guidelines

Benchmarks Significance (p Value)
  • p < .001

    Very strong evidence against the null hypothesis.

  • .001 ≤ p < .01

    Strong evidence against the null hypothesis.

  • .01 ≤ p < .05

    Statistically significant at α = .05. Moderate evidence against the null hypothesis.

  • .05 ≤ p < .10

    Not significant. Weak evidence; sometimes called a “trend.” Treat it as inconclusive.

  • p ≥ .10

    Not significant. Little evidence against the null, which is not the same as evidence of no effect.

These evidence labels are one common convention for describing p in graded language rather than as significant or not; the boundaries are rough guides, not rules, and other authors draw them differently. Muff et al. (2022) argue for this kind of language of evidence over a single cutoff. α is chosen before the analysis, and p never says how big or important an effect is.

More about statistical significance ↓

Benchmarks Effect Size (Cramér's V)
  • V < .07 Below Small

    Tomorrow's state barely depends on today's. (Below Cohen's small; the label is ours.)

  • .07 ≤ V < .21 Small

    Hard to see in the table without computing it.

  • .21 ≤ V < .35 Medium

    A dependence you'd notice by looking at the table's rows.

  • V ≥ .35 Large

    The rows clearly differ: today's state goes a long way toward predicting tomorrow's.

Cohen's (1992) cutoffs for w (.10, .30, .50) converted to V for a 3 × 3 table: V = w ÷ √(m − 1), with m = 3 states, so m − 1 = 2. They were written for associations between two variables, not for day-to-day persistence, so treat them as a rough guide. Benchmarks are conventions, not measures of practical importance.

More about effect size ↓

How It's Reported

Equation Form

Example

p̂low→low = .60, 95% CI [.54, .66], π = (.20, .40, .40), V = .46, G2(4, N = 1,300) = 511.16, p < .001

Table 1. Day-to-Day Mood Transitions

Example
n\hat{p}95% CI
Low → Low 160.60[.54, .66]
Low → Neutral 79.29[.24, .35]
Low → Good 29.11[.07, .15]
Neutral → Low 81.16[.13, .19]
Neutral → Neutral 299.59[.54, .63]
Neutral → Good 129.25[.22, .29]
Good → Low 24.05[.03, .06]
Good → Neutral 137.26[.22, .30]
Good → Good 362.69[.65, .73]

Note. N = 1,300 transitions from 100 people. \hat{p} is the share of moves out of today's mood that went to tomorrow's; each block of three adds to 1. Wald 95% confidence intervals, which assume every transition is independent; with real diary data, use a bootstrap that resamples people (see Run It in Software).

Table 2. Where Moods Settle

Example
Long Run \pi7 Days after Low7 Days after GoodObserved
Low .203.214.196.204
Neutral .398.400.397.395
Good .399.387.407.401

Note. Long run: the stationary distribution of the matrix in Table 1. Seven days on: the chance of each mood a week after a low or a good day, from the matrix raised to the 7th power. Observed: the share of all 1,400 person-days in each mood.

Table 3. Likelihood Ratio Tests

Example
G^2dfp
First order vs. independence 511.164< .001
Second order vs. first order 12.9512.372
Week 1 vs. week 2 (time homogeneity) 3.676.721

Note. Each row compares a simpler model with a richer one. The first is the test of the Markov model; the other two check its assumptions, and there a non-significant result is what the model needs. The second-order test uses the 1,200 transitions that have a previous day. Week 1 = transitions starting on days 1–7 (700); week 2 = transitions starting on days 8–13 (600).

Full Text (APA Style)

Example

Moods persisted from day to day. A low day was followed by another low day 60% of the time, 95% CI [.54, .66], and a good day by another good day 69% of the time [.65, .73]; low days were rarely followed by good ones (11%; Table 1). In the long run the estimated transition matrix settles into 20% low, 40% neutral and 40% good days, matching the observed shares, as it should when those are steady over the study (Table 2), and by a week later a person's starting mood makes little difference. Today's mood was strongly associated with tomorrow's, Cramér's V = .46, and a first-order Markov chain fit far better than a model in which days were independent, G2(4, N = 1,300) = 511.16, p < .001. Adding the previous day did not improve the fit, G2(12) = 12.95, p = .372, nor did the transitions differ between the first and second weeks, G2(6) = 3.67, p = .721 (Table 3).

  • Lead with the transition probabilities and their intervals; the test against independence is a low bar for almost any repeated measure. With real diaries, get the intervals from a bootstrap that resamples people, since each person's transitions are linked.
  • Report the counts behind each row. A probability out of 268 transitions is much firmer than one out of 20.
  • Say how you checked the Markov property and time homogeneity, and that pooling assumes everyone shares one matrix. If people weren't modeled separately, say the persistence may partly reflect stable differences between people.
  • Give N as the number of transitions and say how many people they came from. Italicize p̂, V, G, N and p, and report exact p to three decimals (or p < .001).

Reading Each Piece

The equation form above, piece by piece, in this order: how big, how certain, then how surprising.

p̂low→low = .60 Six in ten low days were followed by another low day. Low days are only 20% of all days, so that's about three times what you'd expect if today told you nothing about tomorrow (step 6 expects 54.6 low-to-low moves; we saw 160). Good days repeated more often (.69), but they're 40% of all days, so that's less than twice their base rate. A low day was followed by a good one only 11% of the time.
95% CI [.54, .66] The true chance that a low day is followed by another is plausibly anywhere from about 54% to 66%, if everyone shares one set of chances.
π = (.20, .40, .40) In the long run the chain spends about 20% of days low, 40% neutral and 40% good, close to the 20%, 40% and 40% of days we actually observed. That match is expected whenever the shares don't drift over the study, so it isn't a test of the model.
V = .46 Today's mood goes a long way toward predicting tomorrow's: large by the benchmarks above. Whether that persistence matters clinically depends on how long low stretches last, about 2.5 days on average here. Benchmarks ↑
G2(4, N = 1,300) = 511.16 How much worse a no-memory model fits than the Markov model; 511 is far past the 9.49 that chance exceeds 5% of the time with 4 df. N is the number of transitions, not people.
p < .001 If today's mood told you nothing about tomorrow's in the pooled data, a fit at least this bad would essentially never happen. That's no surprise: today predicts tomorrow when moods carry over, and also when some people are simply low more often than others. The probabilities are the real result. Benchmarks ↑

Calculations

The Running Example

Example

The mood-diary study: 100 adults, 14 evenings each, every day classified as low, neutral or good, so 13 day-to-day moves per person and 1,300 in all.

Null Hypothesis:
p_{ij} = p_{j} \text{ for every today } i
Alternative:
p_{ij} \neq p_{j} \text{ for some } i

p_{ij} is the chance that a day in mood i is followed by mood j; p_j is the overall chance of mood j tomorrow. The null says today's mood tells you nothing about tomorrow's in the pooled table (a “zero-order” chain); the alternative is a first-order Markov chain. It's a low bar: moods carrying over and some people simply being low more often both reject it, so the interesting results are the probabilities themselves.

What Your Data Should Look Like

One row per consecutive pair of occasions: who it is, when, the state then and the state at the next occasion. If your file has one row per person per occasion, make the pairs by taking each person's next state (a "lead" or "lag" within person); never pair the last day of one person with the first day of the next. Missing occasions break a pair, so drop pairs that skip a day rather than treating them as one step. If occasions are unequally spaced, as with random prompts, a one-step matrix mixes short and long gaps; use a continuous-time Markov model, which allows for the time between occasions.

Our 1,300 pairs (13 per person) become the today × tomorrow table below, with each row's percentages. Those percentages are the estimated transition probabilities.

Example
participantdaymoodnext_mood
11goodgood
12goodneutral
13neutralgood
14goodgood
15goodgood
16goodgood
… 1294 more rows
Tomorrow: LowTomorrow: NeutralTomorrow: GoodTotal
Today: Low160 (60%)79 (29%)29 (11%)268
Today: Neutral81 (16%)299 (59%)129 (25%)509
Today: Good24 (5%)137 (26%)362 (69%)523
Total2655155201300

Counts, with each row's percentages.

Simulated data.

Download all 1300 rows (data.csv)

Napkin Math

The whole test, one idea at a time. Under each heading, a line says why the step matters, and the green note reads the equation in plain English with the mood-diary study's numbers. Collapse all to read just the headings: they tell the whole story on their own.

  1. 1. Count Every Move from One Day to the Next

    Everything starts with a table of moves: for each pair of consecutive days, where the person was today (the row) and where they were tomorrow (the column). Each person's 14 days give 13 moves.

    \begin{array}{l|ccc} & \text{Low} & \text{Neutral} & \text{Good} \\ \hline \text{Low} & n_{LL} & n_{LN} & n_{LG} \\ \text{Neutral} & n_{NL} & n_{NN} & n_{NG} \\ \text{Good} & n_{GL} & n_{GN} & n_{GG} \end{array} =\begin{array}{l|ccc} & \text{Low} & \text{Neutral} & \text{Good} \\ \hline \text{Low} & 160 & 79 & 29 \\ \text{Neutral} & 81 & 299 & 129 \\ \text{Good} & 24 & 137 & 362 \end{array}

    = 1300 transitions

    n_{LL} = 160

    n_{NN} = 299

    n_{GG} = 362

    n_{LL} is the 160 times a low day was followed by another low day. The rows add up to 268 moves out of low days, 509 out of neutral and 523 out of good: 100 people × 13 moves = 1,300.

  2. 2. Turn Each Row of Counts into Chances

    Rows differ in size, so compare shares. Dividing each count by its row total gives the chance of each mood tomorrow, given today's. This is the maximum likelihood estimate of the transition probability.

    \hat{p}_{ij} = \dfrac{n_{ij}}{n_{i\cdot}} =\dfrac{160}{268}

    = .60

    \hat{p}_{NN} = .59

    \hat{p}_{GG} = .69

    n_{LL} is our 160 low-to-low moves and n_{L\cdot} the 268 moves out of low days. 160 ÷ 268 = .60. The other two in the row are 79 ÷ 268 = .29 and 29 ÷ 268 = .11, and the three add up to 1.

  3. 3. Give a Range of Plausible Values for Each Chance

    Each row is like a sample of moves out of one mood, so each chance gets the usual interval for a proportion, with the row total as the sample size.

    \hat{p}_{ij} \pm z^{*}\sqrt{\dfrac{\hat{p}_{ij}(1 - \hat{p}_{ij})}{n_{i\cdot}}} =.597 \pm 1.96\sqrt{\dfrac{.597 \times .403}{268}}

    = [.54, .66]

    SE = .030

    n_{L\cdot} is our 268 moves out of low days. The standard error is √(.597 × .403 ÷ 268) = .030, and 1.96 × .030 = .059, so the range is .597 ± .059, from .54 to .66.

  4. 4. Look Further Ahead by Chaining the Days Together

    To get from low today to good in two days, a person passes through some mood tomorrow. Add up the chances over every route; doing that for every pair of moods is multiplying the matrix by itself.

    P^{(2)} = P \times P, \quad p^{(2)}_{ij} = \sum_{k} p_{ik}\,p_{kj} =.597 \times .108 + .295 \times .253 + .108 \times .692

    = .21

    p^{(7)}_{LG} = .39

    p^{(7)}_{LL} = .21

    p_{Lk} is the chance of going from low to mood k tomorrow and p_{kG} the chance of going from k to good the day after. Low–low–good is .597 × .108, low–neutral–good .295 × .253, low–good–good .108 × .692; together .21. Raised to the 7th power, the matrix says .39 a week later.

  5. 5. Find Where Moods Settle in the Long Run

    Keep chaining and the starting mood stops mattering. The shares the chain settles into are the ones that one more day leaves unchanged: the stationary distribution.

    \pi P = \pi, \quad \sum_{j} \pi_j = 1 =\pi_L = .597\,\pi_L + .159\,\pi_N + .046\,\pi_G

    = .20

    \pi_N = .40

    \pi_G = .40

    \pi_L, \pi_N and \pi_G are the long-run shares of low, neutral and good days. Tomorrow's low days come from today's low days that stay (.597), neutral days that drop (.159) and good days that crash (.046). Solving that equation with the two like it and \pi_L + \pi_N + \pi_G = 1 gives .20, .40 and .40.

  6. 6. Compare with a Model Where Today Doesn't Matter

    If today's mood made no difference, every row would split like the column totals. The likelihood ratio chi-square measures how much worse that simpler model fits the counts than the Markov model does.

    G^2 = 2 \sum_{i,j} O_{ij} \ln\dfrac{O_{ij}}{E_{ij}} =2\left[160 \ln\dfrac{160}{54.6} + 79 \ln\dfrac{79}{106.2} + \cdots + 362 \ln\dfrac{362}{209.2}\right]

    = 511.16

    E_{LL} = 54.6

    O_{ij} is each observed count and E_{ij} what it would be if today didn't matter: 268 × 265 ÷ 1,300 = 54.6 low-to-low moves, against the 160 we saw. Summed over all nine cells and doubled, G^2 = 511.16.

  7. 7. Account for How Much Information the Table Had

    The Markov model estimates two free chances per row (the third is whatever's left), six in all; the no-memory model estimates two. The difference is the degrees of freedom.

    df = (r - 1)(c - 1) =(3 - 1)(3 - 1)

    = 4

    r and c are our 3 moods today and 3 tomorrow, the same 3 states that Cramér's V calls k and the power section calls m. (3 − 1) × (3 − 1) = 4, the same as 6 − 2 extra chances.

  8. 8. Measure How Strongly Today Predicts Tomorrow

    G² grows with the number of transitions; Cramér's V doesn't. It rescales the table's chi-square to run from 0 (today tells you nothing) to 1 (today fixes tomorrow).

    V = \sqrt{\dfrac{\chi^2}{n\,(k - 1)}} =\sqrt{\dfrac{545.96}{1300 \times 2}}

    = .46

    \chi^2 = 545.96

    \chi^2 is Pearson's chi-square for the same table, 545.96, n our 1,300 transitions and k - 1 = 2. 545.96 ÷ 2,600 = .21, and its square root is .46.

  9. 9. Ask How Surprising the Fit Would Be If Today Didn't Matter

    Finally, ask how often chance alone would make the no-memory model fit at least this badly if tomorrow's mood really didn't depend on today's.

    p = P(\chi^2_{df} \ge \chi^2) =P(\chi^2_{4} \ge 511.16)

    < .001

    \chi^2_4 is a chi-square distribution with 4 df. The chance it lands at or above 511.16 is far below .001, less than 1 in 10¹⁰⁸.

Run It in Software

The code below reads the running example's data from data.csv; save it in the same folder you run the code from.

SPSS (version 30, as documented by IBM)

SPSS has no Markov chain procedure, but Crosstabs gives the transition table, its row percentages (the transition probabilities) and the likelihood ratio test against independence.

  1. Analyze → Descriptive Statistics → Crosstabs.
  2. Move mood into Row(s) and next_mood into Column(s).
  3. Click Statistics, check Chi-square and Phi and Cramer's V, and click Continue.
  4. Click Cells, check Observed, Expected and Row percentages, click Continue, then OK.
  5. For the second-order check, make yesterday's mood with the syntax below, then run Crosstabs again with yesterday in Row(s), next_mood in Column(s) and mood in Layer 1 of 1.

Matrix powers and the stationary distribution aren't on any menu; use R or Python (below) for those, or multiply the matrix by hand.

Or paste this syntax:

CROSSTABS
  /TABLES=mood BY next_mood
  /STATISTICS=CHISQ PHI
  /CELLS=COUNT EXPECTED ROW
  /COUNT ROUND CELL.

* Second order: yesterday x tomorrow within each of today's moods.
SORT CASES BY participant day.
STRING yesterday (A7).
IF (participant = LAG(participant)) yesterday = LAG(mood).
MISSING VALUES yesterday ('').
CROSSTABS
  /TABLES=yesterday BY next_mood BY mood
  /STATISTICS=CHISQ.

Reading the Output

Read the % within mood rows first: they're the transition probabilities. Then Cramer's V (the size), then the Likelihood Ratio row of Chi-Square Tests (G², the test of Markov against independence). SPSS sorts the moods alphabetically, so good comes first.

mood * next_mood Crosstabulation (abridged)

good low neutral Total
good Count 362 24 137 523
% within mood 69.2% 4.6% 26.2% 100.0%
low Count 29 160 79 268
% within mood 10.8% 59.7% 29.5% 100.0%
neutral Count 129 81 299 509
% within mood 25.3% 15.9% 58.7% 100.0%

Chi-Square Tests

Value df Asymptotic Significance (2-sided)
Pearson Chi-Square 545.958ᵃ 4 <.001
Likelihood Ratio 511.158 4 <.001
N of Valid Cases 1300

a. 0 cells (0.0%) have expected count less than 5. The minimum expected count is 54.63.

Symmetric Measures: Phi = .648, Cramer's V = .458.

"N of Valid Cases" counts transitions, not people. In the layered second-order table, the three Likelihood Ratio rows (one per mood today) are 2.854, 8.439 and 1.662 on 4 df each; add them for the joint test, G²(12) = 12.95, p = .372. SPSS doesn't add them for you. In the low and good layers one cell each has an expected count below 5 (the smallest is 1.2); that's common in second-order tables, so treat a borderline result there cautiously. With few transitions, pool rare yesterday states or use a multinomial regression with fewer terms.

Output laid out from this page's computed results, not captured from a live run; labels and layout may differ slightly in your version.

R
diary <- read.csv("data.csv")   # one row per transition
states <- c("low", "neutral", "good")
diary$mood <- factor(diary$mood, levels = states)
diary$next_mood <- factor(diary$next_mood, levels = states)

# Transition counts, and each row divided by its total
counts <- table(today = diary$mood, tomorrow = diary$next_mood)
counts
P <- prop.table(counts, 1)
round(P, 3)

# 95% CIs: p ± 1.96 × √(p(1 − p) / row total)
se <- sqrt(P * (1 - P) / rowSums(counts))
round(P - qnorm(0.975) * se, 3)
round(P + qnorm(0.975) * se, 3)

# Two and seven days ahead: powers of the matrix
P2 <- P %*% P
P7 <- P; for (k in 2:7) P7 <- P7 %*% P
round(P2, 3)
round(P7, 3)

# Long run: the eigenvector of t(P) for eigenvalue 1, scaled to add to 1
v <- Re(eigen(t(P))$vectors[, 1])
round(setNames(v / sum(v), states), 3)

# Markov vs independence: tomorrow ~ today as a multinomial regression
library(nnet)   # ships with R
m0 <- multinom(next_mood ~ 1, data = diary, trace = FALSE)
m1 <- multinom(next_mood ~ mood, data = diary, trace = FALSE)
anova(m0, m1)
x2 <- chisq.test(counts)$statistic
sqrt(x2 / (sum(counts) * 2))   # Cramér's V

# Check 1, second order: does yesterday add anything? (the same people, in day order)
diary <- diary[order(diary$participant, diary$day), ]
diary$yesterday <- ave(as.integer(diary$mood), diary$participant, FUN = function(x) c(NA, head(x, -1)))
diary$yesterday <- factor(states[diary$yesterday], levels = states)
d2 <- subset(diary, !is.na(yesterday))
anova(multinom(next_mood ~ mood, data = d2, trace = FALSE),
      multinom(next_mood ~ mood * yesterday, data = d2, trace = FALSE))

# Check 2, time homogeneity: the first week vs the second
diary$week <- factor(ifelse(diary$day <= 7, "first", "second"))
anova(m1, multinom(next_mood ~ mood * week, data = diary, trace = FALSE))

# For real diaries: a bootstrap that resamples people, not transitions
set.seed(2026)
ids <- unique(diary$participant)
rows <- split(seq_len(nrow(diary)), diary$participant)
boot <- replicate(2000, {
  d <- diary[unlist(rows[as.character(sample(ids, replace = TRUE))]), ]
  prop.table(table(d$mood, d$next_mood), 1)["low", "low"]
})
round(quantile(boot, c(0.025, 0.975)), 3)   # low -> low, 95% CI by person
         tomorrow
today     low neutral good
  low     160      79   29
  neutral  81     299  129
  good     24     137  362
         tomorrow
today       low neutral  good
  low     0.597   0.295 0.108
  neutral 0.159   0.587 0.253
  good    0.046   0.262 0.692
         tomorrow
today       low neutral  good
  low     0.538   0.240 0.071
  neutral 0.127   0.545 0.216
  good    0.028   0.224 0.653
         tomorrow
today       low neutral  good
  low     0.656   0.349 0.145
  neutral 0.191   0.630 0.291
  good    0.064   0.300 0.732
         tomorrow
today       low neutral  good
  low     0.408   0.377 0.214
  neutral 0.200   0.458 0.342
  good    0.101   0.349 0.550
         tomorrow
today       low neutral  good
  low     0.214   0.400 0.387
  neutral 0.204   0.399 0.397
  good    0.196   0.397 0.407
    low neutral    good
  0.203   0.398   0.399
  Model Resid. df Resid. Dev   Test    Df LR stat. Pr(Chi)
1     1      2598   2749.580           NA       NA      NA
2  mood      2594   2238.422 1 vs 2     4 511.1577       0
X-squared
  0.45824
             Model Resid. df Resid. Dev   Test    Df LR stat.  Pr(Chi)
1             mood      2394   2065.217           NA       NA       NA
2 mood * yesterday      2382   2052.262 1 vs 2    12 12.95415 0.372382
        Model Resid. df Resid. Dev   Test    Df LR stat.   Pr(Chi)
1        mood      2594   2238.422           NA       NA        NA
2 mood * week      2588   2234.754 1 vs 2     6 3.668804 0.7213923
 2.5% 97.5%
0.534 0.655

The multinomial regression of tomorrow's mood on today's reproduces the transition matrix, and anova prints its likelihood ratio test: G² is the "LR stat." (511.16 on 4 df). Pr(Chi) prints as 0 because p is below R's printing precision; report p < .001. Cramér's V prints under the name X-squared because it was computed from that value. The two checks are the same comparison with yesterday's mood, or the week, added as a predictor. The last lines resample whole people, keeping each person's 13 transitions together. These simulated people all share one matrix, so the person-level interval for low → low (.534 to .655) matches the Wald interval; in real diaries, where people differ, it will usually be wider, and it's the interval to report.

Output from a real run: R 4.6.1 (nnet 7.3-20, which ships with R), run 2026-09-29.

Python
import numpy as np
import pandas as pd
from scipy import stats

diary = pd.read_csv("data.csv")   # one row per transition
states = ["low", "neutral", "good"]
counts = pd.crosstab(diary["mood"], diary["next_mood"]).loc[states, states]
P = counts.div(counts.sum(axis=1), axis=0)          # each row / its total
se = np.sqrt(P * (1 - P) / counts.sum(axis=1).to_numpy()[:, None])
print(P.round(3))
print((P - 1.96 * se).round(3), (P + 1.96 * se).round(3), sep="\n")

print(np.linalg.matrix_power(P.to_numpy(), 7).round(3))    # a week ahead

vals, vecs = np.linalg.eig(P.to_numpy().T)                   # long run
pi = np.real(vecs[:, np.argmax(np.real(vals))])
print((pi / pi.sum()).round(3))

g2 = stats.chi2_contingency(counts, lambda_="log-likelihood")   # Markov vs independence
print(round(g2.statistic, 4), g2.dof, g2.pvalue)
x2 = stats.chi2_contingency(counts).statistic
print(round(np.sqrt(x2 / (counts.to_numpy().sum() * 2)), 4))     # Cramér's V

# Second order vs first: yesterday x tomorrow, within each of today's moods
diary = diary.sort_values(["participant", "day"])
diary["yesterday"] = diary.groupby("participant")["mood"].shift(1)
g_second = sum(stats.chi2_contingency(pd.crosstab(d["yesterday"], d["next_mood"]), lambda_="log-likelihood").statistic
               for _, d in diary.dropna(subset=["yesterday"]).groupby("mood"))
print(round(g_second, 4), round(stats.chi2.sf(g_second, 12), 4))

# First week vs second, row by row
week = np.where(diary["day"] <= 7, "first", "second")
g_time = sum(stats.chi2_contingency(pd.crosstab(week[diary["mood"] == s], diary.loc[diary["mood"] == s, "next_mood"]), lambda_="log-likelihood", correction=False).statistic
             for s in states)
print(round(g_time, 4), round(stats.chi2.sf(g_time, 6), 4))
next_mood    low  neutral   good
mood
low        0.597    0.295  0.108
neutral    0.159    0.587  0.253
good       0.046    0.262  0.692
next_mood    low  neutral   good
mood
low        0.538    0.240  0.071
neutral    0.127    0.545  0.216
good       0.028    0.224  0.653
next_mood    low  neutral   good
mood
low        0.656    0.349  0.145
neutral    0.191    0.630  0.291
good       0.064    0.300  0.732
[[0.214 0.4   0.387]
 [0.204 0.399 0.397]
 [0.196 0.397 0.407]]
[0.203 0.398 0.399]
511.1577 4 2.5865837437851866e-109
0.4582
12.9542 0.3724
3.6688 0.7214

lambda_="log-likelihood" makes scipy's chi2_contingency return G² instead of Pearson's χ². The second-order and week checks add up G² from one small table per mood today, as Anderson and Goodman (1957) do. Sort by person and day before shifting, so yesterday always comes from the same person.

Output from a real run: Python 3.9.6 with pandas 2.3.3, numpy 2.0.2 and scipy 1.13.1, run 2026-09-29.

Impact

Effect Size

A Markov model's natural sizes are its probabilities: how likely each state is to persist, and how likely each kind of switch is. They're in the units readers care about, chances per day, and they're what to compare across studies that used the same states.

A low day was followed by another low day 60% of the time, about three times the 20% of days that are low, and a good day by another good day 69% of the time, against 40% of days that are good. Each low day ends the run with chance 1 − .597 = .403, so a run of low days lasts 1 ÷ .403 ≈ 2.5 days on average before mood lifts.

For one number that says how much today's state predicts tomorrow's, Cramér's V (Cramér, 1946) on the today × tomorrow table works, with k = 3 states:

V = \sqrt{\dfrac{\chi^2}{n\,(k - 1)}} = \sqrt{\dfrac{545.96}{1300 \times 2}} = .46

Today's and tomorrow's moods are associated at V = .46, large by convention for a 3 × 3 table, where Cohen's cutoffs of .10, .30 and .50 for w become .07, .21 and .35.

V runs a little high in small samples. Bergsma's (2013) bias-corrected V reduces that, and with 1,300 transitions it's also .46 here.

V ignores which way the dependence runs and treats every switch alike; it can't say that moods are sticky rather than, say, alternating. Report it next to the diagonal probabilities, not instead of them. Benchmarks are conventions. Whether six-in-ten persistence of low mood is worth an intervention is a clinical question, not a statistical one.

Benchmarks Cramér's V at a Glance
Below Small
V < .07
Small
.07 ≤ V < .21
Medium
.21 ≤ V < .35
Large
V ≥ .35

Full benchmarks and caveats ↑

Statistical Significance

The main p answers one narrow question: if today's state told you nothing about tomorrow's in the pooled table, how often would the counts fit that no-memory model at least this badly? It's a likelihood ratio test of a first-order Markov chain against independence (Anderson & Goodman, 1957). Below the conventional α = .05, the dependence is called statistically significant.

If today's mood told you nothing about tomorrow's, 1,300 transitions would stray at least this far from the no-memory model essentially never, p < .001. That's expected: nearly any daily measure persists, if only because some people are low more often than others.

The same kind of test, comparing a simpler model with a richer one, checks the assumptions. There the roles flip: a non-significant result is what the Markov model needs, and it only says the data couldn't detect a problem.

Adding yesterday's mood didn't help predict tomorrow's, G²(12) = 12.95, p = .372, and the first week's transitions didn't differ from the second's, G²(6) = 3.67, p = .721. That means no problem was detected, not that there's none.

p is not the probability that the Markov model is right, and it says nothing about how sticky moods are. It also treats all 1,300 transitions as fresh information, which is true only if everyone shares one matrix; if people differ, every p on this page is too small, and the main test can come out significant even when no one's mood carries over.

Benchmarks p at a Glance
Very Strong
p < .001
Strong
.001 ≤ p < .01
Significant
.01 ≤ p < .05
Weak
.05 ≤ p < .10
Little
p ≥ .10

Strength of evidence against the null hypothesis.

Full benchmarks and caveats ↑

Power and Sample Size

Power is the chance that a study detects an effect that's really there. For the test of Markov against independence, power depends on how strongly today predicts tomorrow (Cohen's w), the number of transitions, α and the degrees of freedom, (m − 1)² for m states. Because persistence is usually strong, that test rarely needs many transitions. Precision usually decides the design instead: how many moves out of each state you need to pin down its probabilities.

With 3 moods (df = 4), a medium dependence, w = .30, needs about 133 transitions for 80% power. Our w was √(545.96 ÷ 1,300) = .65 (the same as V × √2 = .46 × 1.41), so power was never in doubt. Precision is the harder target: to estimate a low-to-low chance near .60 to within ±.05, you'd need about 369 moves out of low days. We had 268, so our interval is ±.06.

Researchers usually aim for at least 80% power. Plan it before collecting data, using the smallest effect that would matter, and plan the number of occasions for the rarest state you care about: it's the one with the fewest transitions. Remember that more days from the same people add transitions but not independent people; if people differ, more people help more than more days. The calculator counts transitions, not people. Try it:

Other Info

Follow-Up and Post Hoc Tests

Post Hoc Tests

  • Adjusted Residuals: No post hoc tests are needed for the omnibus G². To see which moves drive the dependence, read the per-cell probabilities and their intervals, or each cell's adjusted standardized residual (SPSS Crosstabs → Cells → Adjusted standardized; R's chisq.test()$stdres). In the mood-diary study, low → low and good → good stand out most (+17.9 and +17.6), followed by the rare jumps between the extremes, good → low and low → good (−11.6 and −10.9), and then neutral → neutral (+11.3).

References

  • Anderson, T. W., & Goodman, L. A. (1957). Statistical inference about Markov chains. The Annals of Mathematical Statistics, 28(1), 89–110. https://doi.org/10.1214/aoms/1177707039
    “Maximum likelihood estimates and their asymptotic distribution are obtained for the transition probabilities in a Markov chain of arbitrary order when there are repeated observations of the chain.” (Summary, p. 89)
  • de Haan-Rietdijk, S., Kuppens, P., Bergeman, C. S., Sheeber, L. B., Allen, N. B., & Hamaker, E. L. (2017). On the use of mixed Markov models for intensive longitudinal data. Multivariate Behavioral Research, 52(6), 747–767. https://doi.org/10.1080/00273171.2017.1370364
    “Sometimes the state-switching process that researchers are interested in is not directly observed, or is observed with methods that are expected to involve substantial measurement error.” (The latent Markov model (LMM))
    “In psychological research with ILD, we expect individual differences in the process parameters, and the data contains enough information to allow these differences to be modeled.” (Approaches to individual differences in the Markov literature)
  • Cohen, J. (1992). A power primer. Psychological Bulletin, 112(1), 155–159. https://doi.org/10.1037/0033-2909.112.1.155
  • Cramér, H. (1946). Mathematical methods of statistics. Princeton University Press.
  • Bergsma, W. (2013). A bias-correction for Cramér's V and Tschuprow's T. Journal of the Korean Statistical Society, 42(3), 323–328. https://doi.org/10.1016/j.jkss.2012.10.002
  • Muff, S., Nilsen, E. B., O'Hara, R. B., & Nater, C. R. (2022). Rewriting results sections in the language of evidence. Trends in Ecology & Evolution, 37(3), 203–210. https://doi.org/10.1016/j.tree.2021.10.009
    “we suggest language of evidence that allows for a more nuanced approach to communicate scientific findings as a simple and intuitive alternative to statistical significance testing” (Abstract)
  • Sharpe, D. (2015). Your chi-square test is statistically significant: Now what? Practical Assessment, Research & Evaluation, 20(8), 1–10. https://doi.org/10.7275/tbfa-x148
    “MacDonald and Gardner (2000) suggest a Bonferroni adjustment to the z critical of 1.96 (from which the +/- 2 criteria is derived) if the number of cells in the contingency table is large.” (p. 3)

Spot an error? Something still confusing? Tell us at support@statsforpsychology.com.