rmarkov-chains

How to make a reproducible example of 2nd Markov Chain Model or Higher in R?


I will start define a vector of values like this:

data <- c(2.3, 1.7, 1.7, 1.4, 1.7, 2.0, 2.2, 1.8, 1.7, 1.6, 2.0, 1.5, 1.1, 1.4, 1.8, 2.0, 1.5, 1.2, 1.0, 1.2, 1.5, 1.6, 1.1,
      1.5, 2.0, 2.1, 2.1, 2.0, 1.7, 1.7, 1.7, 1.3, 0.8, -0.1, 0.0, -0.1, -0.2, 0.0, 0.1, 0.2, 0.2, 0.0, 0.2, 0.5, 0.7, 1.4,
      1.0, 0.9, 1.1, 1.0, 1.0, 0.8, 1.1, 1.5, 1.6, 1.7, 2.1, 2.5, 2.7, 2.4, 2.2, 1.9, 1.6, 1.7, 1.9, 2.2, 2.0, 2.2, 2.1,
      2.1, 2.2, 2.4, 2.5, 2.8, 2.9, 2.9, 2.7, 2.3, 2.5, 2.2, 1.9, 1.6, 1.5, 1.9, 2.0, 1.8, 1.6, 1.8, 1.7, 1.7, 1.8, 2.1,
      2.3, 2.5, 2.3, 1.5, 0.3, 0.1, 0.6, 1.0, 1.3, 1.4, 1.2, 1.2, 1.4, 1.4, 1.7, 2.6, 4.2, 5.0, 5.4, 5.4, 5.3, 5.4, 6.2,
      6.8, 7.0, 7.5, 7.9, 8.5, 8.3, 8.6, 9.1, 8.5, 8.3, 8.2, 7.7, 7.1, 6.5, 6.4, 6.0, 5.0, 4.9, 4.0, 3.0, 3.2, 3.7, 3.7)

And From this vector I make an ifelse statement to represent its "Increase", "Decrease", and "Stagnant"

direction <- c(0,diff(data))
direction_states <- ifelse(direction > 0, "Increase", ifelse(direction < 0, "Decrease", "Stagnant"))

And finally have a dataframe from these 2 respective keys:

df_track <- as.data.frame(cbind(data, direction_states))
df_track <- df_track[-1,]

This is how i constructed a First Order Markov Chain using the package markovchain

library(markovchain)
direction_states_diff <- c(df_track$direction_states[2:nrow(df_track)])
transition_matrix <- as.matrix(table(df_track$direction_states[1:length(direction_states_diff)], direction_states_diff) / rowSums(table(df_track$direction_states[1:length(direction_states_diff)], direction_states_diff)))
transition_matrix <- as.numeric(transition_matrix)
dim(transition_matrix) <- c(3, 3)
transition_matrix[is.na(transition_matrix)] <- 0
markov_chain <- new("markovchain", states = c("Decrease", "Increase", "Stagnant"), 
                    transitionMatrix = transition_matrix, name = "Markov 1st Order Value")
print(markov_chain)

          Decrease  Increase   Stagnant
Decrease 0.5614035 0.3333333 0.10526316
Increase 0.2537313 0.6567164 0.08955224
Stagnant 0.5833333 0.3333333 0.08333333

set.seed(123) 
simulated_states <- rmarkovchain(n = 10, object = markov_chain, t0 = tail(df_track$direction_states, 1))
print(simulated_states)

But I am unable to reproduce an example to make 2nd or Higher Markov Model, since this statements:

markov_chain <- new("markovchain", states = c("Decrease", "Increase", "Stagnant"), 
                        transitionMatrix = transition_matrix, name = "Markov 1st Order Value")

Only allows me an input of 2D Matrix, not 3D or above. showing an error like this:

Error in validObject(.Object) : 
  invalid class “markovchain” object: invalid object for slot "transitionMatrix" in class "markovchain": got class "array", should be or extend class "matrix"

Help is Appreciated!


Solution

  • I think i just found the answers, there is this function called fitHigherOrder() in the markovchain package, when I try to execute it like this:

    high_order4 <- fitHigherOrder(df_track$direction_states, 4) #using 4 orders
    

    I get these results:

    $lambda
    [1] 2.026152e-08 3.087294e-07 9.999995e-01 1.391219e-07
    
    $Q
    $Q[[1]]
              Decrease   Increase   Stagnant
    Decrease 0.5614035 0.25373134 0.58333333
    Increase 0.3333333 0.65671642 0.33333333
    Stagnant 0.1052632 0.08955224 0.08333333
    
    $Q[[2]]
               Decrease  Increase   Stagnant
    Decrease 0.47368421 0.3787879 0.33333333
    Increase 0.49122807 0.4848485 0.58333333
    Stagnant 0.03508772 0.1363636 0.08333333
    
    $Q[[3]]
              Decrease   Increase   Stagnant
    Decrease 0.4035088 0.46153846 0.16666667
    Increase 0.4912281 0.46153846 0.75000000
    Stagnant 0.1052632 0.07692308 0.08333333
    
    $Q[[4]]
               Decrease   Increase   Stagnant
    Decrease 0.42857143 0.44615385 0.16666667
    Increase 0.48214286 0.46153846 0.75000000
    Stagnant 0.08928571 0.09230769 0.08333333
    
    
    $X
      Decrease   Increase   Stagnant 
    0.41605839 0.48905109 0.09489051 
    

    That Q[[1]] is almost the same as the result of First Order Markov Chain above except this one printed a column-wise results (that sums into a probability of 1) while above First Order Markov Chain printed a row-wise results. Hence if I do this, I can reproduce it:

    for(g in 1:length(order4$Q)){
      order4$Q[[g]] <- t(order4$Q[[g]])
    }
    
    markov_chain_order2 <- new("markovchain", states = c("Decrease", "Increase", "Stagnant"), 
                        transitionMatrix = order4$Q[[2]], name = "Markov 2nd Order Value")
    print(markov_chain_order2)
    set.seed(123) # for reproducibility
    simulated_states <- rmarkovchain(n = 10, object = markov_chain_order2, t0 = tail(df_track$direction_states, 1))
    print(simulated_states)
    

    If by Q[[2]] and above represents its second order Markov Chain probabilites or above in 2D Matrix. (Still, Correct me if I am wrong)