(R) Применение сумм бегущих строк в табличном объекте с 2 переменными - PullRequest
1 голос
/ 02 октября 2019

Ниже приводится реплицированная выборка данных, которая записывает продолжительность 300 пропусков. month - это первый месяц отсутствия, а length - это количество одновременных месяцев, в течение которых оно отсутствовало.

df <- data.frame("month" = sample(c("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"),300, replace = TRUE),
           "length" = sample.int(6, size = 300, replace = TRUE))

df$month <- factor(df$month, levels(df$month)[c(5,4,8,1,9,7,6,2,12,11,10,3)])

Используя table(df$length), вы можете увидеть, сколько отдельных пропусков длилось ровно для каждого значенияlength.

1  2  3  4  5  6 
55 45 42 56 51 51 

Но поскольку length является инкрементным, если бы я хотел показать общее количество пропусков, которые достигли (но не обязательно длились) определенного количества месяцев, я мог бы использовать rev(cumsum(rev(table(df$length)))) который дает:

 1   2   3   4   5   6 
300 245 200 158 102  51

Мне интересно видеть это кумулятивное представление month. rev(cumsum(rev(table(df$month,df$length)))) возвращает вектор, а не таблицу.

В результате я хотел бы взять это

table(df$month, df$length)

       1  2  3  4  5  6
  jan  5  5  4  5  3  2
  feb  5  7  2  7  9  3
  mar  5  3  2  2  9  4
  apr  6  7  4  4  3 11
  may  5  5  3  5  5  2
  jun  4  4  2  7  4  5
  jul  4  3  5  5  1  4
  aug  4  0  5  3  6  7
  sep  4  5  4  4  3  3
  oct  4  2  1  6  5  4
  nov  5  2  3  5  2  2
  dec  4  2  7  3  1  4

и превратить его в это, где вычисляется обратный кумулятивный счет lengthдля каждого month.

       1   2   3   4   5   6
  jan  24  19  14  10  5   2
  feb  33  28  21  19  12  3
  mar  25  20  17  15  13  4
  apr  35  29  22  18  14 11
  may  25  20  15  12  7   2
  jun  26  22  18  16  9   5
  jul  22  18  15  10  5   4
  aug  25  21  21  16  13  7
  sep  23  19  14  10  6   3
  oct  22  18  16  15  9   4
  nov  19  14  12  9   4   2
  dec  21  17  15  8   5   4

Есть ли способ сделать это с помощью table()? Если нет, я открыт для любого решения. Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 03 октября 2019

Если вы создаете фрейм данных, а не объект класса таблицы, вы можете использовать Reduce с + в качестве функции и accumulate = T для получения суммы. Перед созданием «таблицы» (в кавычках, поскольку класс не является «таблицей») я сделал факторную версию столбца месяца, чтобы месяцы оставались в том же порядке.

df$month_fac <- with(df, factor(month, levels = unique(month)))
tbl <- data.table::dcast(df, month_fac ~ length)
tbl[ncol(tbl):2] <- Reduce('+', rev(tbl[-1]),  accumulate = TRUE)

Выводtbl объект, но я не потрудился показать его, потому что вы не установили начальное значение, поэтому (случайные) значения будут отличаться от результатов, показанных в вопросе.

1 голос
/ 03 октября 2019

Мы можем использовать rowCumsums в столбцах rev, используя индекс с seq (:), обратным для индекса столбца, а затем rev снова индексировать

library(matrixStats)
tbl <- table(df$month, df$length)
tbl[] <- rowCumsums(tbl[, ncol(tbl):1])[, ncol(tbl):1]
tbl
#     
#       1  2  3  4  5  6
#  jan 24 19 14 10  5  2
#  feb 33 28 21 19 12  3
#  mar 25 20 17 15 13  4
#  apr 35 29 22 18 14 11
#  may 25 20 15 12  7  2
#  jun 26 22 18 16  9  5
#  jul 22 18 15 10  5  4
#  aug 25 21 21 16 13  7
#  sep 23 19 14 10  6  3
#  oct 22 18 16 15  9  4
#  nov 19 14 12  9  4  2
# dec 21 17 15  8  5  4

Или в base R это будет cumsum с apply

tbl[] <- t(apply(tbl[, ncol(tbl):1], 1, cumsum))[, ncol(tbl):1]

data

tbl <-  structure(c(5L, 5L, 5L, 6L, 5L, 4L, 4L, 4L, 4L, 4L, 5L, 4L, 5L, 
    7L, 3L, 7L, 5L, 4L, 3L, 0L, 5L, 2L, 2L, 2L, 4L, 2L, 2L, 4L, 3L, 
    2L, 5L, 5L, 4L, 1L, 3L, 7L, 5L, 7L, 2L, 4L, 5L, 7L, 5L, 3L, 4L, 
    6L, 5L, 3L, 3L, 9L, 9L, 3L, 5L, 4L, 1L, 6L, 3L, 5L, 2L, 1L, 2L, 
    3L, 4L, 11L, 2L, 5L, 4L, 7L, 3L, 4L, 2L, 4L), .Dim = c(12L, 6L
    ), .Dimnames = structure(list(c("jan", "feb", "mar", "apr", "may", 
    "jun", "jul", "aug", "sep", "oct", "nov", "dec"), c("1", "2", 
    "3", "4", "5", "6")), .Names = c("", "")), class = "table")
...