AndrejFlina
AndrejFlina

Reputation: 35

Creating Transition Matrices for Markov - summing to 1

I am building a transition matrix for some markov chains, so I need all rows to add up to 1.

I create a random ten-state 10 x 10 matrix with:

new_vector <- runif(10^2,0,1)

new_matrix <- matrix(new_vector,
                     ncol=10,
                     nrow=10,
                     byrow=TRUE,
                     dimnames=list(from_state=sprintf("State_No.%s", rep(1:10)),
                                   to_state=sprintf("State_No.%s", rep(1:10)))

But when I use apply() , {x/sum(x)} it still sums by columns and not by rows even if I've indicated margin=1.

I've succeeded by transposing and retransposing the matrix back again as below, but is there a quicker way? I have tried Rowsum and Rowsums but the error that this flags is that these functions operate on more than one dimension like an array, so not 1 line of x in a matrix.

  transition_matrix <- new_matrix %>%
       t() %>%
       apply(1, function(x) {x/sum(x)}) %>%
       t()

Upvotes: 0

Views: 448

Answers (2)

Baraliuh
Baraliuh

Reputation: 2141

Could do this:

library(magrittr)
runif(10^2,0,1) %>% matrix(
    ncol=10,
    nrow=10,
    byrow=TRUE,
    dimnames=list(from_state=sprintf("State_No.%s", rep(1:10)),
                  to_state=sprintf("State_No.%s", rep(1:10)))) %>% 
    {./rowSums(.)}
#>              to_state
#> from_state     State_No.1   State_No.2 State_No.3  State_No.4 State_No.5
#>   State_No.1  0.006094192 2.368840e-01 0.01945430 0.009640636 0.10569798
#>   State_No.2  0.089365247 2.983981e-02 0.11105866 0.213237034 0.27210071
#>   State_No.3  0.045070840 1.668207e-01 0.11398683 0.070080118 0.13006391
#>   State_No.4  0.125118802 6.759151e-02 0.16539060 0.041190822 0.07925457
#>   State_No.5  0.070762472 3.043250e-02 0.12622707 0.103491689 0.13099049
#>   State_No.6  0.106804592 7.487430e-03 0.09698103 0.236750897 0.07901013
#>   State_No.7  0.092574755 4.299522e-05 0.08152285 0.105494645 0.17246980
#>   State_No.8  0.074693534 3.242886e-02 0.16875275 0.105159611 0.07136171
#>   State_No.9  0.244717854 2.627272e-02 0.12778209 0.016028245 0.07431306
#>   State_No.10 0.078546516 1.979094e-02 0.08570224 0.132081330 0.03534794
#>              to_state
#> from_state    State_No.6 State_No.7 State_No.8 State_No.9 State_No.10
#>   State_No.1  0.11168487 0.08117511 0.16877487 0.02440833 0.236185686
#>   State_No.2  0.01047526 0.02289755 0.17762330 0.07049188 0.002910546
#>   State_No.3  0.15781163 0.15601041 0.05030479 0.02224956 0.087601240
#>   State_No.4  0.02452016 0.18252079 0.10150099 0.09967102 0.113240736
#>   State_No.5  0.03431670 0.13189689 0.17937359 0.06447137 0.128037228
#>   State_No.6  0.04742069 0.06046898 0.04538069 0.27748477 0.042210797
#>   State_No.7  0.15050511 0.08957707 0.07137909 0.12003282 0.116400862
#>   State_No.8  0.08937574 0.10161565 0.05289538 0.17533034 0.128386422
#>   State_No.9  0.08811830 0.23903120 0.01375217 0.06387515 0.106109199
#>   State_No.10 0.08754714 0.06245419 0.16050361 0.17046485 0.167561241
runif(10^2,0,1) %>% matrix(
    ncol=10,
    nrow=10,
    byrow=TRUE,
    dimnames=list(from_state=sprintf("State_No.%s", rep(1:10)),
                  to_state=sprintf("State_No.%s", rep(1:10)))) %>% 
    {./rowSums(.)} %>% 
    rowSums()
#>  State_No.1  State_No.2  State_No.3  State_No.4  State_No.5  State_No.6 
#>           1           1           1           1           1           1 
#>  State_No.7  State_No.8  State_No.9 State_No.10 
#>           1           1           1           1

Created on 2022-02-03 by the reprex package (v2.0.0)

Upvotes: 0

Onyambu
Onyambu

Reputation: 79188

Any of the codes below will work

prop.table(new_matrix, 1)

proportions(new_matrix, 1)

new_matrix / rowSums(new_matrix)

sweep(new_matrix, 1, rowSums(new_matrix), '/')

t(apply(new_matrix, 1, function(x)x/sum(x)))

Upvotes: 1

Related Questions