0

我正在使用按包group_by功能分组的数据集dplyr。每个组都有它自己的时间索引,即假定由 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 中是否有任何简单的方法可以做到这一点,也许是对 package.json 函数的一些修改/组合tibbletime

任何帮助将不胜感激。

先感谢您。

4

2 回答 2

0

您可以使用summarise函数 fromdplyr返回一个逻辑值,判断每个 中是否有大于 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")

在此处输入图像描述

于 2018-05-11T15:25:27.497 回答
0

以下是我通常使用的方法来解决这个问题data.table—— base 中的cut.Date()and函数是逻辑的核心,因此如果需要,您可以使用相同的方法。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]
于 2018-05-11T16:53:43.043 回答