0

I'm trying to run a data frame through multiple transitions of a Markov model for a class.

The data frame looks like this:

df = pd.DataFrame({'Bull Market': [.9, .8, .5],
                   'Bear Market': [.25, .05, .25],
                   'Stagnant Market': [.75, .15, .25]
                  },
                  index=["Bull Market", "Bear Market", "Stagnant Market"])

I have this code for running it through twice:

print(df.dot(df))

I need to run it through the model X times. I had a difficult time finding documentation on dot(), but from what I did find, it does not appear that you can run it through X times.

Any help would be appreciated, thank you!

Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144

1 Answers1

0

That's not the way a Markov chain works. You need a starting state (in this case, either [1,0,0], [0,1,0], or [0,0,1]), then you left multiply the transition matrix by the state vector, then multiply the transition matrix by the newly attained state vector, etc. You don't multiply the transition matrix by itself. If you need to figure what happens after a specific number of transitions, you can just loop through X times and perform X matrix-vector multiplies. If you want the steady state, you need to find the dominant eigenvector, which you can do using numpy.linalg.eig. Note also that this won't work with the transition matrix you have, because those rows are not probability distributions.

Edit: Okay, I think I see what you're trying to do. Because of the way matrix vector multiplication works, you can also just exponentiate the matrix, then multiply it by the starting state vector, and get the same result as if you had iteratively multiplied each intermediate result. You can use numpy.linalg.matrix_power to do that. And I see you got that matrix from Wikipedia. You just miscopied some of those numbers, i.e. should be 0.025, not 0.25. It's critical that every row sums to 1.

This code reproduces the example from Wikipedia:

import numpy as np

T = np.array([[0.9, 0.075, 0.025],
              [0.15, 0.8, 0.05],
              [0.25, 0.25, 0.5]])
start = np.array([0, 1, 0])

def find_state_after_n(start, T, n):
    Tmult = np.linalg.matrix_power(T, n)
    state = np.dot(start, Tmult)
    return state

find_state_after_n(start, T, 3)

array([ 0.3575 ,  0.56825,  0.07425])
Adam Acosta
  • 603
  • 3
  • 6
  • Thanks for your help. I created the matrix based off of a diagram I was given for my class with three different items/columns (I don't know the right terminology.) The example problem I was given only had two, so I was very confused as to how to put the three column matrix together in order to equal 1. My setup worked to equal 1, just not in the proper order as you mentioned. I will review your code and also the Wikipedia entry that you found. An additional note, in the example I was given, the columns equaled 1 instead of the rows. I will continue to research more examples of this in action. – Ryan Kuhle Nov 17 '15 at 19:23
  • It actually works either way. If you use the transpose of this matrix so the columns sum to 1 instead of the rows, you just have to right multiply then, i.e. above change `state = np.dot(start, Tmult)` to `state = np.dot(Tmult, start)`. – Adam Acosta Nov 17 '15 at 22:24