R 如何计算从一个状态到另一个状态的转换次数?
我有下面的向量R 如何计算从一个状态到另一个状态的转换次数?,r,for-loop,if-statement,counting,R,For Loop,If Statement,Counting,我有下面的向量 [1] 1 3 5 1 1 4 3 4 5 1 1 2 2 3 1 1 2 4 3 4 4 4 1 1 1 由以下代码段生成 set.seed(5) my.matrix = round(matrix(data = runif(n = 25, min = 0, max = 5), ncol = 5),0) my.vec = as.vector(my.matrix) 我知道我可以计算每个数字的采样频率,并将其存储在一个数据帧中 freq = as.data.frame(table
[1] 1 3 5 1 1 4 3 4 5 1 1 2 2 3 1 1 2 4 3 4 4 4 1 1 1
由以下代码段生成
set.seed(5)
my.matrix = round(matrix(data = runif(n = 25, min = 0, max = 5), ncol = 5),0)
my.vec = as.vector(my.matrix)
我知道我可以计算每个数字的采样频率,并将其存储在一个数据帧中
freq = as.data.frame(table(my.vec))
现在假设这个向量中的每个数字都是一个状态S
如何计算从一个状态到下一个状态的所有可能转换发生的次数
例如,有多少次S
从1变为1,从1变为2,从1变为3,依此类推
我试图计算一个转移矩阵,但到目前为止,我执行这项任务的唯一想法是使用一个包含16个不同的
if
语句的for
循环。这似乎不是最佳的选择 下面是一个使用1 for循环的完整示例。关键是使用expand.grid构建所有可能的转换(注意,您需要在my.vec
周围使用unique
命令,因为有些转换会多次发生)
一旦有了网格,只需在for循环中单步遍历向量,提取当前和下一个元素,在网格中标识它所属的索引,并将其递增+1。代码如下
library(dplyr)
set.seed(5)
my.matrix = round(matrix(data = runif(n = 25, min = 0, max = 5), ncol = 5),0)
my.vec = as.vector(my.matrix)
result <- expand.grid(unique(my.vec), unique(my.vec)) %>% mutate(count = 0)
for (i in 1:(length(my.vec)-1)){
currentVal = my.vec[i]
nextVal = my.vec[i+1]
result[result$Var1 == currentVal & result$Var2==nextVal,]$count = result[result$Var1 == currentVal & result$Var2==nextVal,]$count +1
}
库(dplyr)
种子(5)
my.matrix=round(矩阵(数据=runif(n=25,min=0,max=5),ncol=5,0)
my.vec=as.vector(my.matrix)
结果%变异(计数=0)
对于(i in 1:(长度(my.vec)-1)){
currentVal=my.vec[i]
nextVal=my.vec[i+1]
结果[result$Var1==currentVal&result$Var2==nextVal,]$count=result[result$Var1==currentVal&result$Var2==nextVal,]$count+1
}
如果要剪切从未发生转换的行,请执行以下操作:
resultNoZeros <- result %>% filter(count > 0)
resultNoZeros%筛选器(计数>0)
通过set.seed(101)模拟数据;z下面的伪代码可能会有所帮助:
您有一个25元素的向量/数组。每个元素是一个从1到5的数字。按照惯例,让我们调用vectorvec
,并假设元素的索引范围为0到24
您需要一个二维数组(本质上是一个矩阵),让我们称它为m
,这样m[0][0]
就是第0行第0列(第一行第一列)。初始条件是矩阵中的每个坐标值为0
我们将在每次迭代中使用并重新使用两个变量,以确定矩阵中的哪个单元格必须递增。我们称之为a和b<代码>a
将是每个步骤的“自”值,b
将是步骤的“至”值
的第一次迭代)
a
,然后继续(结束迭代)
b
中记录其值(3),此时,a=1
和b=3
b。找到第一行第三列的矩阵元素(类似于矩阵[1][3]
),并将其当前值(0)增加1,这样现在矩阵[1][3]=1
c。在继续之前,我们需要为下一步做好准备,因此将b
的当前值分配给a
(现在a=3
,以便在下一次迭代中充当“from”)。暂时不要使用b
,因为它的当前值与下一次迭代无关
d。转到循环的下一次迭代(移动到向量中的下一个元素(即5),并在步骤2a重新开始
(此时,b
应取当前元素值(5),因此您可以转到矩阵[a][b]
并将该元素的当前值增加1)
冲洗并重复,直到完成for循环并设置完毕
正如您所看到的,您根本不需要任何if
结构……只需要一个移动指针,它允许您读取数组元素的值
有更有效的方法可以做到这一点,但这应该足够了您不需要那么多if语句…只需创建一个填充有零的二维数组(矩阵)并沿着向量走…在每个步骤上记录初始值和最终值(在您的示例中,第一步是从1到3,下一步是从3到5,依此类推)找到与初始-最终对相对应的矩阵元素(例如矩阵[1][3]),将其增加一个,然后再进行一步……因此,您只需要一个
循环,而不需要任何其他内容作为注释,Javier。但我如何“记录初始和最终状态”?同样,我只知道如何使用if语句。for
循环将引导您遍历数组/向量(每次迭代将把您放在一个数组元素上).不需要if。只需阅读您正在使用的值,然后转到下一个值。我不熟悉R,但这是一个足够基本的构造,可以用伪代码来描述。伪代码中更详细的答案对您有用吗?是的,我认为确实会有帮助。如果您能为我编写它,我将不胜感激。好了……对不起,我接受了很长。我在手机上写字,但我不是打字最快的人:)嗨,本。谢谢你的回答,但我认为你的建议有问题。出于某种原因,它无法计算相同状态之间的转换。数据中的前6个元素是2 1 4 2 2
,从结果中可以看出,[2,2]和[4,4]处的计数为零,这不是真的。@MasonBeau Ben抢先告诉了我,但你应该能够将他的最后一行调整到表(my.vec[-length(my.vec)],my.vec[-1])
。我想这会给你你想要的。嘿,@hmhensen,谢谢你的输入,但是这会如何改变代码不计算相等状态之间的转换的事实呢?您编写的代码行是Ben的最后一行代码,但是使用了my.vec
而不是v
。不是吗?@MasonBeau是sa
table(z[-length(z)],z[-1])
1 2 3 4 5
1 4 4 2 3 3
2 5 4 4 3 4
3 2 2 2 5 5
4 4 2 5 6 7
5 2 7 3 7 4
v <- rle(z)$values
table(v[-length(v)],v[-1])
1 2 3 4 5
1 0 4 2 3 3
2 5 0 4 3 4
3 2 2 0 5 5
4 4 2 5 0 7
5 2 7 3 7 0