Подмножество временных рядов для получения начала и конца непрерывного временного ряда в списке

#r #time-series

#r #временные ряды

Вопрос:

Это кажется простым, но после долгих поисков и попыток я этого не понял:

У меня есть список временных рядов, краткий пример для воспроизведения:

 a <- seq(as.Date("1970-01-01"), as.Date("1970-01-05"), "days")
b <- seq(as.Date("1985-10-01"), as.Date("1985-10-05"), "days")
c <- seq(as.Date("2014-03-01"), as.Date("2014-03-05"), "days")
d <- c(a, b, c)
df1 <- data.frame(d)
colnames(df1) <- c("date")
e <- seq(as.Date("1975-01-01"), as.Date("1975-01-05"), "days")
f <- seq(as.Date("1990-10-01"), as.Date("1990-10-05"), "days")
g <- c(e, f)
df2 <- data.frame(g)
colnames(df2) <- c("date")
ll <- list(df1, df2)
  

Теперь я хочу подмножество перечисленных данных.кадры для:

 > llsubset
[[1]]
        date
1 1970-01-01
2 1970-01-05
3 1985-10-01
4 1985-10-05
5 2014-03-01
6 2014-03-05

[[2]]
        date
1 1975-01-01
2 1975-01-05
3 1990-10-01
4 1990-10-05
  

Я пробовал это с помощью rollapply , но это не работает, и это не стоит смотреть. Может быть, вы можете мне помочь? Спасибо!

Ответ №1:

Определите, какие точки отличаются от предыдущих более чем на 1 день, и из этого постройте логическое с ИСТИНОЙ в концах каждой последовательности и ЛОЖЬЮ в другом месте. Подмножество по нему. Пакеты не используются.

 lapply(ll, subset, { dif <- diff(date) > 1; c(TRUE, dif) | c(dif, TRUE) } )
  

предоставление:

 [[1]]
         date
1  1970-01-01
5  1970-01-05
6  1985-10-01
10 1985-10-05
11 2014-03-01
15 2014-03-05

[[2]]
         date
1  1975-01-01
5  1975-01-05
6  1990-10-01
10 1990-10-05
  

Комментарии:

1. Мне нравится использование | .

Ответ №2:

Может быть, что-то вроде этого? Используйте cumsum и diff для создания групповой переменной, а затем подмножьте свою дату (при условии, что вы пытаетесь узнать минимальную и максимальную дату в течение каждого последовательного периода времени и date сортируется в порядке возрастания перед рукой):

 library(dplyr)
lapply(ll, function(df) {
            df %>% 
                  group_by(cumsum(c(TRUE, diff(date) != 1))) %>% 
                  slice(c(1, n())) %>% 
                  ungroup() %>% 
                  select(date) }
      )

#[[1]]
# A tibble: 6 × 1
#        date
#      <date>
#1 1970-01-01
#2 1970-01-05
#3 1985-10-01
#4 1985-10-05
#5 2014-03-01
#6 2014-03-05

#[[2]]
# A tibble: 4 × 1
#        date
#      <date>
#1 1975-01-01
#2 1975-01-05
#3 1990-10-01
#4 1990-10-05
  

Ответ №3:

Вероятно, есть пакет, который делает именно это, но я пока не знаю его названия.

Использование diff() для дат может выделить, какие даты имеют только один день между ними, вот так:

 diff(df1$date)
Time differences in days
 [1]     1     1     1     1  5748     1     1     1     1 10374     1
[12]     1     1     1
  

Мы можем использовать это.

 end_finder <- function(x) {
  # find the gap between dates.
  # mark dates where the diff > 1,
  # also mark the entry prior to that one;
  # this will be the end of the previous date.
  # also include the first and last element.

  diff_dates <- c(100,diff(x$dates))
  diff_idx <- which(diff_dates > 1)
  diff_idx <- c((diff_idx -1 ), diff_idx)
  # remove any elements < 1
  diff_idx <- diff_idx[diff_idx >= 1 ]
  # include the first element
  diff_idx <- c(1, diff_idx)
  # include the last element
  diff_idx <- c(diff_idx, length(x$date))
  # remove duplicates and sort for easier reading
  diff_idx <- sort(unique(diff_idx))
  x$dates[diff_idx]
}
  

Теперь запустите это.

 > lapply(ll, end_finder)
[[1]]
[1] "1970-01-01" "1970-01-05" "1985-10-01" "1985-10-05" "2014-03-01"
[6] "2014-03-05"

[[2]]
[1] "1975-01-01" "1975-01-05" "1990-10-01" "1990-10-05"
  

Ответ №4:

Другое решение с использованием dplyr : сначала мы вычисляем год для каждой даты и для каждого года находим минимальную и максимальную дату, используя year и melt функции из пакетов lubridate и reshape2 соответственно

 library(dplyr)
library(lubridate)
library(reshape2)

ll <- list(df1, df2)


fn_endPoint_Years = function(DF) {

newDF = DF %>%  
mutate(Year=year(date)) %>% 
group_by(Year) %>% 
do(.,data.frame(minDate=min(.$date),maxDate=max(.$date) )) %>% 
melt(id="Year",value.name = "date") %>% 
arrange(date) %>% 
select(date)

}

lapply(ll,fn_endPoint_Years)

# [[1]]
        # date
# 1 1970-01-01
# 2 1970-01-05
# 3 1985-10-01
# 4 1985-10-05
# 5 2014-03-01
# 6 2014-03-05

# [[2]]
        # date
# 1 1975-01-01
# 2 1975-01-05
# 3 1990-10-01
# 4 1990-10-05