rollapply с функцией rle(x)

У меня есть данные временных рядов как класс data.table, и каждый столбец (точки наблюдения) имеет значения, которые я хочу подсчитать в скользящем окне (ширина 30). Я пытался использовать rle(sort(x)) для подсчета всех значений в rollapply, но это не работает.

например, если у меня есть таблица, как показано ниже,

dt <- data.frame(v1=c(1,0,1,4,4,4,4,4),v2=c(1,1,1,4,3,3,3,3),
          v3=c(0,1,1,3,3,3,3,2),v4=c(1,1,0,3,3,3,3,3),
       v5=c(1,1,1,5,5,5,5,5))

Я пробовал так;

rollapply(dt, 3, function(x) {rle(sort(x))$values; rle(sort(x))$length})

но результат просто не имеет смысла. пожалуйста, дайте мне какое-нибудь направление...


person kclick    schedule 24.01.2014    source источник
comment
Я не вижу никаких data.table выше. Но что еще более важно, непонятно, чего вы хотите - пожалуйста, предоставьте желаемый результат.   -  person eddi    schedule 24.01.2014
comment
извините за не ясный вопрос. желаемый результат был для каждого скользящего окна, которое я хотел иметь отсортированное значение с номером появления (счетчик). Я могу превратить свой dt в dt1‹-data.table(dt)   -  person kclick    schedule 24.01.2014


Ответы (1)


Решение 1 Предположим, что цель состоит в том, чтобы получить скользящее количество из 3 значений, попробуйте следующее:

m <- as.matrix(dt)
levs <- sort(unique(c(m)))
f <- function(x) table(factor(x, levs))
r <- rollapply(m, 3, f)

Здесь levs равно 0, 1, ..., 5, поэтому для каждого применения функции мы получим вектор длиной 6 с количеством 0, 1, ..., 5. Есть 5 входных столбцов, поэтому применение такой функции к каждому столбцу дает 5 * 6 = 30 выходных столбцов.

Обратите внимание, что rollapply работает с матрицами или объектами зоопарка, а не с фреймами данных, поэтому мы преобразовали его. Кроме того, чтобы гарантировать, что каждое приложение функции выводит вектор одинаковой длины, мы конвертируем каждый вход в фактор с одинаковыми уровнями.

Обратите внимание, что:

ra <- array(r, c(6, 6, 5))

дает трехмерный массив, в котором ra[,,i] представляет собой матрицу, образованную rollapply(dt[, i], 3, f). То есть в матрице ra[,,i] есть строка для каждого применения f в столбце i, и столбцы в этой строке подсчитывают количество 0, 1, ..., 5.

Другая возможность - это то, что дает те же 5 матриц (по одной на входной столбец) в качестве компонентов результирующего списка:

lapply(dt, rollapply, 3, f)

Например, рассмотрим следующее. Строка 1 вывода говорит, что первое применение f к dt[,1] имеет один 0, две единицы и никаких других значений. Это также можно получить от r[,,1] или от lapply(dt, rollapply, 3, f)[[1]] :

> rollapply(dt[, 1], 3, f)
     0 1 2 3 4 5
[1,] 1 2 0 0 0 0  <- dt[1:3,1] has 1 zero and 2 ones
[2,] 1 1 0 0 1 0  <- dt[2:4,1] has 1 zero and 1 one and 1 four, etc.
[3,] 0 1 0 0 2 0
[4,] 0 0 0 0 3 0
[5,] 0 0 0 0 3 0
[6,] 0 0 0 0 3 0

Решение 2

Это говорит о том, что глядя на ячейку 1,1 вывода, есть один 0 и две единицы в dt[1:3,1]. Глядя на ячейку 2,1 вывода, мы видим, что в dt[2:4,1] есть один 0, один 1 и 1 четыре, и т. д.

> g <- function(x) { tab <- table(x); toString(paste(names(tab), tab, sep = ":")) }
> sapply(dt, rollapply, 3, g) # or rollapply(m, 3, g) where m was defined in solution 1
     v1              v2              v3         v4              v5        
[1,] "0:1, 1:2"      "1:3"           "0:1, 1:2" "0:1, 1:2"      "1:3"     
[2,] "0:1, 1:1, 4:1" "1:2, 4:1"      "1:2, 3:1" "0:1, 1:1, 3:1" "1:2, 5:1"
[3,] "1:1, 4:2"      "1:1, 3:1, 4:1" "1:1, 3:2" "0:1, 3:2"      "1:1, 5:2"
[4,] "4:3"           "3:2, 4:1"      "3:3"      "3:3"           "5:3"     
[5,] "4:3"           "3:3"           "3:3"      "3:3"           "5:3"     
[6,] "4:3"           "3:3"           "2:1, 3:2" "3:3"           "5:3"     

ДОБАВЛЕНО: Дополнительное обсуждение и решение 2.

person G. Grothendieck    schedule 24.01.2014
comment
Спасибо за ответ. но очень сложно интерпретировать результат. то, что я действительно хочу получить, это - если я просто использую данные выше dt, используя скользящее окно шириной 5. Для столбца v1 для первого скользящего окна 1 имеют 2 счета, 0 - 1, 4 - 2, во втором скользящем окне - 1 - 1, 0 - 1, 4 - 3 счета. и т. д. Поэтому, когда я просто запускаю rle(sort(x)) x как простой вектор, вы получаете отсортированные значения результата с общим количеством. Это то, что я хочу иметь в своем скользящем окне, но... я не знаю, почему функция rle не очень хорошо применяется в функции rollapply - person kclick; 24.01.2014
comment
Проблема с кодом в вопросе заключается в том, что функция, заданная для rollapply, возвращает выходные данные разной длины в зависимости от входных значений, поэтому она не может преобразовать результат в прямоугольник. Я добавил дополнительное обсуждение и второе решение. - person G. Grothendieck; 24.01.2014
comment
это было чрезвычайно полезно. Я постараюсь все переварить и дам вам знать, если у меня возникнут еще вопросы относительно вашего подхода. - person kclick; 24.01.2014
comment
Еще раз, спасибо за помощь. Могу ли я также добавить код для извлечения значений и их максимального количества в каждом скользящем окне? - person kclick; 25.01.2014
comment
В решении 2 замените table(x) на sort(table(x)), и тогда значения и количество будут в порядке счета, поэтому последнее будет максимальным. Если вам нужно только максимальное значение и его количество, замените table(x) на tail(sort(table(x)), 1). Есть и другие вариации в зависимости от того, что вам нужно. Просто измените g соответствующим образом. - person G. Grothendieck; 25.01.2014