Как я могу посчитать количество переходов из одного состояния в другое? - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть следующий вектор

[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 и т. Д.

Я пытаюсь вычислитьматрица переходов, но единственная идея, которую я до сих пор имел для выполнения этой задачи, заключалась в использовании цикла for с 16 различными операторами if.Кажется, это не оптимальный путь.

Ответы [ 3 ]

0 голосов
/ 06 декабря 2018

Имитация данных через set.seed(101); z <- sample(1:5,size=100,replace=TRUE);извините, я не видел, чтобы у вас была функция генерирования данных в вашем вопросе ...

Чтобы получить все переходы следующего шага: таблица (текущий) vs (следующий):

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

С другой стороны, если вам нужны только переходы между различными состояниями , то есть между прогонами (rle = "кодирование по длине прогона"):

Получите значения каждого«Выполнить» в данных

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
0 голосов
/ 06 декабря 2018

Вот псевдокод, который может помочь:

У вас есть вектор / массив из 25 элементов.Каждый элемент представляет собой число от 1 до 5. Для соглашения давайте назовем вектор vec и предположим, что элементы проиндексированы от 0 до 24

. Вам нужен двумерный массив (по сути, матрица), давайтеназовите его m, чтобы m[0][0] было строкой 0, столбцом 0 (первая строка, первый столбец).Исходным условием является то, что каждая координата в матрице имеет значение 0

. Мы будем использовать и повторно использовать две переменные на каждой итерации, чтобы определить, какая ячейка в матрице должна быть увеличена.Мы будем называть их а и б.a будет значением шага "from", а b будет значением шага "to"

  1. STEP ONE (первая итерация цикла for)

Поскольку это первый элемент массива, мы просто присвоим его значение (1) a и продолжим (завершение итерации)

ШАГИ ВТОРОЙ К 25

a.Перейдите к следующему элементу в векторе и запишите его значение (3) в переменную b, в этой точке a = 1 и b = 3

b.Найдите матричный элемент для первой строки, третьего столбца (что-то вроде matrix[1][3]) и увеличьте его текущее значение (0) на единицу, так что теперь matrix[1][3] =1

c.Прежде чем двигаться дальше, нам нужно подготовиться к следующему шагу, поэтому присвойте текущее значение b на a (теперь a = 3, чтобы на следующей итерации он действовал как "с").Оставьте пока b в покое, поскольку его текущее значение не имеет значения до следующей итерации.

d.Перейти к следующей итерации цикла for (перейти к следующему элементу в векторе (который равен 5) и начать заново с шага 2a

(На этом этапе b должен взять текущий элементзначение (5), поэтому вы переходите к matrix[a][b] и увеличиваете текущее значение этого элемента на единицу)

Промойте и повторяйте, пока не завершите цикл for и не установите

Как видите, вам вообще не нужны if структуры ... Просто движущийся указатель, который позволяет вам читать значение элемента массива

. Есть даже более эффективные способы сделать это, но этого должно быть достаточно.

0 голосов
/ 06 декабря 2018

Вот полный пример использования 1 для цикла.Ключ заключается в том, чтобы построить все возможные переходы с помощью expand.grid (обратите внимание, что вам нужна команда unique вокруг my.vec, поскольку некоторые переходы происходят более одного раза).

После того, как вы получите эту сетку, просто выполните шагиваш вектор в цикле 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
}

Если вы хотите вырезать строки, в которых переход никогда не происходит:

resultNoZeros <- result %>% filter(count > 0)
...