Reputation: 35
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
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
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