Проверить индекс временного ряда - PullRequest
0 голосов
/ 11 мая 2018

Я использую набор данных, сгруппированный по функции group_by пакета dplyr. Каждая группа имеет свой собственный временной индекс, который предположительно состоит из 12-месячных последовательностей. Это означает, что он может начинаться с января и заканчиваться в декабре, а в других случаях он может начинаться с июня предыдущего года и заканчиваться в мае следующего года.

Вот пример набора данных:

     ID       DATE
      8 2017-01-31
      8 2017-02-28
      8 2017-03-31
      8 2017-04-30
      8 2017-05-31
      8 2017-06-30
      8 2017-07-31
      8 2017-08-31
      8 2017-09-30
      8 2017-10-31
      8 2017-11-30
      8 2017-12-31
     32 2017-01-31
     32 2017-02-28
     32 2017-03-31
     32 2017-04-30
     32 2017-05-31
     32 2017-06-30
     32 2017-07-31
     32 2017-08-31
     32 2017-09-30
     32 2017-10-31
     32 2017-11-30
     32 2017-12-31
     45 2016-09-30
     45 2016-10-31
     45 2016-11-30
     45 2016-12-31
     45 2017-01-31
     45 2017-02-28
     45 2017-03-31
     45 2017-04-30
     45 2017-05-31
     45 2017-06-30
     45 2017-07-31
     45 2017-08-31

Проблема в том, что я не могу подтвердить или проверить визуально из-за измерений набора данных, если есть так называемые «скачки», другими словами, если даты совпадают. Есть ли какой-нибудь простой способ сделать это, возможно, некоторая модификация / комбинация функций из пакета tibbletime.

Любая помощь будет оценена.

Заранее спасибо.

Ответы [ 2 ]

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

Вот как я бы обычно подходил к этой проблеме, используя data.table - функции cut.Date() и seq.Date() из базы являются основой логики, поэтому при желании вы можете использовать тот же подход с dplyr.

library(data.table)

## Convert to data.table
setDT(df)

## Convert DATE to a date in case it wasn't already
df[,DATE := as.Date(DATE)]

## Order by ID and Date
setkey(df,ID,DATE)

## Create a column with the month of each date
df[,Month := as.Date(cut.Date(DATE, breaks = "months"))]

## Generate a sequence of Dates by month for the number of observations
## in each group -- .N
df[,ExpectedMonth := seq.Date(from = min(Month),
                              by = "months",
                              length.out = .N), by = .(ID)]

## Create a summary table to test whether an ID had 12 observations where
## the actual month was equal to the expected month
Test <- df[Month == ExpectedMonth, .(Valid = ifelse(.N == 12L,TRUE,FALSE)), by = .(ID)]

print(Test)
#    ID Valid
# 1:  8  TRUE
# 2: 32  TRUE
# 3: 45  TRUE

## Do a no-copy join of Test to df based on ID
## and create a column in df based on the 'Valid' column in Test
df[Test, Valid := i.Valid, on = "ID"]

## The final output:
head(df)
#    ID       DATE      Month ExpectedMonth Valid
# 1:  8 2017-01-31 2017-01-01    2017-01-01  TRUE
# 2:  8 2017-02-28 2017-02-01    2017-02-01  TRUE
# 3:  8 2017-03-31 2017-03-01    2017-03-01  TRUE
# 4:  8 2017-04-30 2017-04-01    2017-04-01  TRUE
# 5:  8 2017-05-31 2017-05-01    2017-05-01  TRUE
# 6:  8 2017-06-30 2017-06-01    2017-06-01  TRUE

Вы также можете сделать что-то более компактно, если вы действительно хотите использовать самообъединение и пропустить создание Test

setDT(df)

df[,DATE := as.Date(DATE)]
setkey(df,ID,DATE)
df[,Month := as.Date(cut.Date(DATE, breaks = "months"))]
df[,ExpectedMonth := seq.Date(from = min(Month), by = "months", length.out = .N), keyby = .(ID)]
df[df[Month == ExpectedMonth,.(Valid = ifelse(.N == 12L,TRUE,FALSE)),keyby = .(ID)], Valid := i.Valid]
0 голосов
/ 11 мая 2018

Вы можете использовать функцию summarise из dplyr для возврата логического значения того, есть ли какие-либо различия в днях, превышающие 31 в каждом ID.Вы делаете это, сначала создавая временную дату, используя только год и месяц и добавляя «-01» в качестве фальшивого дня:

library(dplyr)
library(lubridate)

df %>%
  group_by(ID) %>%
  mutate(DATE2 = ymd(paste0(sub('\\-\\d+$', '', DATE),'-01')),
         DATE_diff = c(0, diff(DATE2))) %>%
  summarise(Valid = !any(DATE_diff > 31))

Результат:

# A tibble: 3 x 2
     ID Valid
  <int> <lgl>
1     8  TRUE
2    32  TRUE
3    45  TRUE

Вы также можете визуально проверить, есть ли какие-либо пробелы, нанося на график свои даты для каждого ID:

library(ggplot2)

df %>%
  mutate(DATE = ymd(paste0(sub('\\-\\d+$', '', DATE),'-01')),
         ID = as.factor(ID)) %>%
  ggplot(aes(x = DATE, y = ID, group = ID)) + 
  geom_point(aes(color = ID)) +
  scale_x_date(date_breaks = "1 month",
               date_labels = "%b-%Y") +
  labs(title = "Time Line by ID")

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...