在R中为马尔可夫模型创建转移矩阵

时间:2017-12-15 18:01:02

标签: r markov-chains

我需要有关马尔可夫链和数据预处理主题的帮助。 假设我有以下矩阵将个人与州联系起来:

     ID Time1 Time2
1 14021     A     A
2 15031     B     A
3 16452     A     C

我想为这个矩阵获得状态转移矩阵: 因此,需要的是

  A  B  C
A 1  0  1
B 1  0  0
C 0  0  0

和同样的事情,但现在加权来自该状态的转换数量,即

  A    B   C
A 0.5  0  0.5
B 1    0   0
C 0    0   0

(因为有两个过渡从状态A离开)。我知道markovchain包有一个功能 如果有一个序列,比如AAABBAAABBCC那么这样做,但是如果像我一样设置数据则不行。 理想情况下,直接程序会很棒,但是如果有某种方法可以将数据转换成一组可以正常工作的序列。

有什么想法吗?

提前致谢

3 个答案:

答案 0 :(得分:3)

这是另一个base R解决方案。

df <- data.frame(Time1 = c("A","B","A"), Time2 = c("A","A","C"), stringsAsFactors = FALSE)

myStates <- sort(unique(c(df$Time1, df$Time2)))
lenSt <- length(myStates)

currState <- match(df$Time1, myStates)
nextState <- match(df$Time2, myStates)
transMat <- matrix(0L, lenSt, lenSt)

transMat[cbind(currState, nextState)] <- 1L
transMat <- transMat/rowSums(transMat)
transMat[is.na(transMat)] <- 0

transMat
     [,1] [,2] [,3]
[1,]  0.5    0  0.5
[2,]  1.0    0  0.0
[3,]  0.0    0  0.0

答案 1 :(得分:3)

采用igraph方式,所以使用Joseph的答案中的df

library(igraph)

g <- graph_from_data_frame(df)

E(g)$weight = 1/degree(g, mode="out")[df$Time1] # get counts

as_adj(g, attr = "weight", sparse=FALSE) # output weighted adjacency matrix

    A B   C
A 0.5 0 0.5
B 1.0 0 0.0
C 0.0 0 0.0

答案 2 :(得分:2)

绝对有更好的方法。这是我在星期五下午蹩脚的圈子里涂鸦。

lvls <- sort(unique(unlist(df[,-1])))

dat <- matrix(0, nrow= length(lvls), ncol= length(lvls))

colnames(dat) <- lvls
rownames(dat) <- lvls

concat <- paste0(df[,2], df[,3])

for (i in 1:length(lvls)) {
  for (j in 1:length(lvls)) {
    dat[i,j] <- paste0(rownames(dat)[i], colnames(dat)[j])
  }
}

dat <- matrix(sapply(dat, function(x) length(grep(x, concat))), 
       nrow= length(lvls), ncol= length(lvls))

colnames(dat) <- lvls
rownames(dat) <- lvls

dat

##   A B C
## A 1 0 1
## B 1 0 0
## C 0 0 0

dat <- dat / rowSums(dat)
dat[is.na(dat)] <- 0

dat

##    A B   C
##A 0.5 0 0.5
##B 1.0 0 0.0
##C 0.0 0 0.0