将数据拆分为具有最少数量的NA的时间段

时间:2017-12-18 17:42:27

标签: r date dataframe data.table subset

我需要将我的数据分成3个不同的时间段,但我希望以每个Y的间隙数最少(缺少数据)的方式进行。这是我的数据:

Data <- data.frame(
  Y = c(rep("A",10),rep("B",10),rep("C",10),rep("D",10),rep("E",10)),
  X = c(sample(seq(as.Date('2017/03/01'), as.Date('2017/09/01'), by="day"), 10),sample(seq(as.Date('2017/03/01'), as.Date('2017/09/01'), by="day"), 10),c(as.Date('2017/05/02'),sample(seq(as.Date('2017/05/01'), as.Date('2017/09/01'), by="day"), 9)),sample(seq(as.Date('2017/03/01'), as.Date('2017/09/01'), by="day"), 10),c(as.Date('2017/05/03'),sample(seq(as.Date('2017/05/01'), as.Date('2017/09/01'), by="day"), 9)))
)

将它分成3个相等的时间段看起来像:

library(lattice)
xyplot(Data$Y ~ Data$X,,
       panel = function(x, y) {
         panel.xyplot(x, y)
         panel.abline(v=c(as.Date('2017/05/01'),as.Date('2017/07/01')))
       })

enter image description here

在这种情况下,如果我将第一个时段定义为2017/03/01至2017/05/03,而不是2017/04/30,我将不会为C组和E组提供NA第一个时期,这就是我想要的。

所以我希望这3个时期是:

  • 第1期:2017年3月1日至2017年4月30日
  • 期间2:2017/05/01至2017/06/30
  • 期间3:2017/07/01至2017/09/30

但是,这些时期的开始/结束可以灵活多达10天。有没有办法做到这一点,而不是视觉上看?

1 个答案:

答案 0 :(得分:1)

由于我们可以移动两个边界,每个边界在10个单位的间隔内,因此有21x21 = 441个选项。这似乎小到暴力(或者这是一个简化的数据集,你的实际问题更大?)。

无论如何,这里有一些非常不理想的代码可以满足您的需求:

Data <- data.frame(
  Y = c(rep("A",10),rep("B",10),rep("C",10),rep("D",10),rep("E",10)),
  X = c(sample(seq(as.Date('2017/03/01'), as.Date('2017/09/01'), by="day"), 10),sample(seq(as.Date('2017/03/01'), as.Date('2017/09/01'), by="day"), 10),c(as.Date('2017/05/02'),sample(seq(as.Date('2017/05/01'), as.Date('2017/09/01'), by="day"), 9)),sample(seq(as.Date('2017/03/01'), as.Date('2017/09/01'), by="day"), 10),c(as.Date('2017/05/03'),sample(seq(as.Date('2017/05/01'), as.Date('2017/09/01'), by="day"), 9)))
)

split1 = as.Date('2017/05/01')
split2 = as.Date('2017/07/01')

library(dplyr)
argmin=[i,j]
minimum = 999

for(i in seq(-10,10))
{
  for(j in seq(-10,10))
  {
    df = Data %>% group_by(Y) %>% summarize(period1 = sum(X<(split1+i)),
                                       period2 = sum(X>=(split1+i) & X<(split2+j)),
                                       period3 = sum(X>=(split2+j)))
    if(sum(df==0)<minimum)
    {
      argmin = c(i,j)
      minimum = sum(df==0)
    }

  }
}

cat(paste0("period 1: 2017-03-01 to ",split1+argmin[1]-1,"\n"))
cat(paste0("period 2: ",split1+argmin[1]," to ",split2+argmin[2]-1,"\n"))
cat(paste0("period 3: ",split2+argmin[2]," to 2017-09-30 \n"))
cat(paste0("Total NA's: ", minimum))

输出:

period 1: 2017-03-01 to 2017-05-03
period 2: 2017-05-04 to 2017-06-20
period 3: 2017-06-21 to 2017-09-30 
Total NA's: 0