A base
альтернатива.
1.Поиск и подсчет пар
Поскольку у вас есть только числовые значения, мы приводим данные в матрицу.Это сделает последующие вычисления значительно быстрее.Создайте версии запаздывания и опережения (по столбцам) данных, т.е. удалите последний столбец (m[ , -ncol(m)]
) и первый столбец (m[ , -ncol(m)]
) соответственно.
Приведите данные запаздывания и опережения к «от»и векторы «to» и количество пар (table
).Преобразовать таблицу в матрицу.Выберите первую пару с максимальной частотой.
m <- as.matrix(d)
tt <- table(from = as.vector(m[ , -ncol(m)]), to = as.vector(m[ , -1]))
m2 <- cbind(from = as.integer(dimnames(tt)[[1]]),
to = rep(as.integer(dimnames(tt)[[2]]), each = dim(tt)[1]),
freq = as.vector(tt))
m3 <- m2[which.max(m2[ , "freq"]), ]
# from to freq
# 3 0 3
Если вы хотите все пары с максимальной частотой, используйте m2[m2[ , "freq"] == max(m2[ , "freq"]), ]
.
2,Замените значения наиболее часто встречающейся пары и установите нулевое значение покоя
Сделайте копию исходных данных.Заполните это с нуля.Возьмите значения from и to для максимальной пары.Получите индексы совпадений в данных отставания и отведения, которые соответствуют столбцам «от».rbind
с индексами столбцов 'to'.В индексах замените нули на 2.
m_bin <- m
m_bin[] <- 0
ix <- which(m[ , -ncol(m)] == m3["from"] &
m[ , -1] == m3["to"],
arr.ind = TRUE)
m_bin[rbind(ix, cbind(ix[ , "row"], ix[ , "col"] + 1))] <- 2
m_bin
# var1 var2 var3 var4 var5
# [1,] 0 0 2 2 0
# [2,] 0 0 2 2 0
# [3,] 2 2 0 0 0
# [4,] 0 0 0 0 0
3.Эталонный тест
Я использую данные, размер которых несколько похож на размер, упомянутый OP в комментарии: фрейм данных с 10000 строками, 100 столбцами и выборкой из 100 различных значений.
Iсравните код выше (f_m()
) с ответом zoo
(f_zoo()
; функции ниже).Чтобы сравнить вывод, я добавляю dimnames
к результату zoo
.
Результат показывает, что f_m
значительно быстрее.
set.seed(1)
nr <- 10000
nc <- 100
d <- as.data.frame(matrix(sample(1:100, nr * nc, replace = TRUE),
nrow = nr, ncol = nc))
res_f_m <- f_m(d)
res_f_zoo <- f_zoo(d)
dimnames(res_f_zoo) <- dimnames(res_f_m)
all.equal(res_f_m, res_f_zoo)
# [1] TRUE
system.time(f_m(d))
# user system elapsed
# 0.12 0.01 0.14
system.time(f_zoo(d))
# user system elapsed
# 61.58 26.72 88.45
f_m <- function(d){
m <- as.matrix(d)
tt <- table(from = as.vector(m[ , -ncol(m)]),
to = as.vector(m[ , -1]))
m2 <- cbind(from = as.integer(dimnames(tt)[[1]]),
to = rep(as.integer(dimnames(tt)[[2]]),
each = dim(tt)[1]),
freq = as.vector(tt))
m3 <- m2[which.max(m2[ , "freq"]), ]
m_bin <- m
m_bin[] <- 0
ix <- which(m[ , -ncol(m)] == m3["from"] &
m[ , -1] == m3["to"],
arr.ind = TRUE)
m_bin[rbind(ix, cbind(ix[ , "row"], ix[ , "col"] + 1))] <- 2
return(m_bin)
}
f_zoo <- function(d){
pairs <- sort(table(c(rollapply(t(d), 2, toString))))
top <- scan(text = names(tail(pairs, 1)), sep = ",", what = 0L, quiet = TRUE)
right <- rollapplyr(unname(t(d)), 2, identical, top, fill = FALSE)
left <- rbind(right[-1, ], FALSE)
t(2 * (left | right))
}