R 验证时间序列索引

R 验证时间序列索引,r,dplyr,tibbletime,R,Dplyr,Tibbletime,我使用的数据集是按dplyr包的group\u函数分组的。 每组都有自己的时间指数,即假定由12个月序列组成。 这意味着它可以从1月开始,到12月结束,或者在其他情况下,它可以从前年6月开始,到明年5月结束 以下是数据集示例: 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

我使用的数据集是按
dplyr
包的
group\u
函数分组的。 每组都有自己的时间指数,即假定由12个月序列组成。 这意味着它可以从1月开始,到12月结束,或者在其他情况下,它可以从前年6月开始,到明年5月结束

以下是数据集示例:

     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
问题是,如果存在所谓的“跳跃”,换句话说,如果日期一致,由于数据集维度的原因,我无法直观地确认或验证。在r中有什么简单的方法可以做到这一点,也许是对
tibbletime
包中的函数进行一些修改/组合

任何帮助都将不胜感激


提前感谢。

您可以使用
dplyr
中的
summary
功能返回每个
ID
内是否存在大于31的日差的逻辑值。为此,首先只使用年和月构造一个临时日期,并附加“-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

以下是我通常使用
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

你需要更具体一些。“如果日期一致”,您的意思是所有组从1月开始到12月结束吗?@用户不一定,他们可以在任何月份开始,但必须是12个月的序列。如果
ID
有12个月,但跳过了一个月,该怎么办?这算是有效的吗?不幸的是,事实并非如此。我知道这个功能,但我需要的是找出是否有遗漏的月份。i、 e.月数为12个月,但从2016-08年到2016-12年,然后从2017-03年到2017-08年。因此,计数将为12,但仍然缺少几个月。谢谢。@user3185925编辑了我的答案。看看这是否是您现在正在寻找的。@用户和Matt,我想感谢您的新想法和良好的实施。
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
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]