Добавить столбец в таблицу со значениями в зависимости от даты - PullRequest
0 голосов
/ 07 мая 2018

У меня есть таблица с датами в виде числа и значения с каждой датой. Теперь я хотел бы добавить еще один столбец weekSum, который содержит сумму значений за последнюю неделю. Однако некоторые даты отсутствуют (поэтому я не всегда могу использовать текущую и последние 6 строк). Моя таблица выглядит так:

df <- data.frame('date' = c(20160309, 20160310, 20160311, 20160312, 20160313, 20160314, 20160315, 20160317, 20160318, 20160319, 20160321), 'value' = c(1, 2, 3, 4, 5, 6, 7 ,8, 9, 10, 11))

date        value
20160309     1
20160310     2
20160311     3
20160312     4
20160313     5
20160314     6
20160315     7
20160316     8     
20160318     9     #17th skipped
20160319    10     
20160321    11     #20th skipped

Я хотел бы получить следующее в качестве вывода:

date        value    weekSum
20160309     1       NA
20160310     2       NA
20160311     3       NA
20160312     4       NA
20160313     5       NA
20160314     6       NA
20160315     7       28    # 1+2+3+4+5+6+7
20160316     8       35    # 2+3+4+5+6+7+8
20160318     9       39    # 4+5+6+7+8+9
20160319    10       45    # 5+6+7+8+9+10
20160321    11       45    # 7+8+9+10+11

Как это можно сделать?

Ответы [ 3 ]

0 голосов
/ 07 мая 2018

1) Преобразовать фрейм данных в зоопарк и определить функцию weekSum, которая подготавливает свои входные данные для последней недели и суммирует их. Затем используйте rollapplyr с coredata = FALSE, чтобы он передавал объект-зоопарк со временем, а не только данные ядра, в функцию weekSum.

library(zoo)

z <- read.zoo(df, format = "%Y%m%d")
weekSum <- function(z) sum(z[time(z) > tail(time(z), 1) - 7])
transform(df, weekSum = rollapplyr(z, 7, weekSum, fill = NA, coredata = FALSE))

дает:

               date value weekSum
2016-03-09 20160309     1      NA
2016-03-10 20160310     2      NA
2016-03-11 20160311     3      NA
2016-03-12 20160312     4      NA
2016-03-13 20160313     5      NA
2016-03-14 20160314     6      NA
2016-03-15 20160315     7      28
2016-03-16 20160316     8      35
2016-03-18 20160318     9      39
2016-03-19 20160319    10      45
2016-03-21 20160321    11      45

2) Альтернативой является заполнение значения в отсутствующие даты нулем, а затем просто используйте rollsumr с шириной 7. z от (1).

z0 <- merge(z, zoo(, seq(start(z), end(z), "day")), fill = 0)
transform(df, weekSum = rollsumr(z0, 7, fill = NA)[z0 != 0])
0 голосов
/ 07 мая 2018

Вот подход с использованием tidyverse инструментов. Этот метод использует tidyr::complete для построения полной последовательности дат, что позволяет легко взять текущую строку и предыдущие 6 в соответствии с предложением. Будьте осторожны, если есть NA значения в value для начала, так как в настоящее время эти строки будут отфильтрованы в конце. Твики можно избежать этого случая при необходимости.

library(tidyverse)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#> 
#>     date
df <- data.frame('date' = c(20160309, 20160310, 20160311, 20160312, 20160313, 20160314, 20160315, 20160317, 20160318, 20160319, 20160321), 'value' = c(1, 2, 3, 4, 5, 6, 7 ,8, 9, 10, 11))
df %>%
  mutate(date = ymd(date)) %>%
  complete(date = seq.Date(min(date), max(date), by = 1)) %>%
  arrange(date) %>%
  mutate(
    newval = replace_na(value, 0),
    weekSum = newval + lag(newval) + lag(newval, 2) + lag(newval, 3) +
      lag(newval, 4) + lag(newval, 5) + lag(newval, 6)
  ) %>%
  select(-newval) %>%
  filter(!is.na(value))
#> # A tibble: 11 x 3
#>    date       value weekSum
#>    <date>     <dbl>   <dbl>
#>  1 2016-03-09    1.     NA 
#>  2 2016-03-10    2.     NA 
#>  3 2016-03-11    3.     NA 
#>  4 2016-03-12    4.     NA 
#>  5 2016-03-13    5.     NA 
#>  6 2016-03-14    6.     NA 
#>  7 2016-03-15    7.     28.
#>  8 2016-03-17    8.     33.
#>  9 2016-03-18    9.     39.
#> 10 2016-03-19   10.     45.
#> 11 2016-03-21   11.     45.

Создано в 2018-05-07 пакетом Представить (v0.2.0).

0 голосов
/ 07 мая 2018

С базой R это можно сделать так:

res <- merge(df, data.frame(date = seq(df$date[1], to = df$date[length(d)], by = "days")), all.y = TRUE)

res$weekSum <- NA
for(i in seq_along(res$sum)[-seq_len(6)]){
    res$weekSum[i] <- sum(res$value[(i - 6):i], na.rm = TRUE)
}
res <- res[!is.na(res$value), ]
res
#         date value sum weekSum
#1  2016-03-09     1  NA      NA
#2  2016-03-10     2  NA      NA
#3  2016-03-11     3  NA      NA
#4  2016-03-12     4  NA      NA
#5  2016-03-13     5  NA      NA
#6  2016-03-14     6  NA      NA
#7  2016-03-15     7  28      28
#9  2016-03-17     8  33      35
#10 2016-03-18     9  39      42
#11 2016-03-19    10  45      49
#13 2016-03-21    11  45      56
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...