根据一年中某一天的日期提取data.table子集

时间:2014-06-04 21:13:32

标签: r date data.table

我有一个这样的数据表:

library(data.table)
set.seed(3)
test <- data.table(date=as.Date(Sys.time())+runif(1000,1,365))
test[, year := as.integer(format(date, "%Y"))]
test

我需要根据今天的日期对其进行子集化,但似乎我在这里犯了一个错误:

test[date %in% (as.Date(paste(year,"-06-04",sep="")) + (-3:3)),]

test[date %in% (as.Date(paste(as.integer(format(date, "%Y")),"-06-04",sep="")) + (-3:3)),]

以下命令有效,但给我一个警告:

test[as.character(date) %in% as.character(as.Date(paste(year,"-06-04",sep="")) + (-3:3)),]

任何想法??

2 个答案:

答案 0 :(得分:1)

我不认为我完全理解这个问题......但是这有帮助吗?看起来你想要在今天的3天内观察所有观察结果而不管年份?

test <- data.table(date=as.IDate(Sys.time())+runif(1000,1,365))
test[month(date)==6 & abs(mday(date)-4)<=3]

答案 1 :(得分:0)

OP有asked for an explanation为什么他的两种方法&#34;不起作用&#34;为什么第三个发出警告。

令我惊讶的是,答案比我预期的更难找到,调查给了我一些新的见解。

要调查的问题

更准确地说,所有三种方法都会产生相同的警告信息:

  

在unclass(e1)+ unclass(e2)中:
  较长的物体长度不是较短物体长度的倍数

此外,前两种方法遇到错误情况但只返回

  

清空2个cols的data.table(0行):date,year

警告信息的说明

在所有三种方法中,OP通过组合长度为1000的向量(例如,%in%)和长度为7的向量(as.Date(paste(year,"-06-04",sep="")))来创建-3:3运算符的RHS。在R中,根据需要回收较短的向量(当它们仅以分数回收时发出警告),请参阅help("Arithmetic")

这可以用一个简单的例子来证明

1:10 + (-3:3)
[1] -2  0  2  4  6  8 10  5  7  9

Warning message:
In 1:10 + (-3:3) :
  longer object length is not a multiple of shorter object length

最有可能的是,上面的结果不是OP的想法。我想他想要将第一个向量的每个元素与第二个向量的每个元素组合在一起。这可以通过outer()功能或使用expand.grid()data.table的交叉加入CJ()来实现:

outer(1:10, -3:3, "+")
      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
 [1,]   -2   -1    0    1    2    3    4
 [2,]   -1    0    1    2    3    4    5
 [3,]    0    1    2    3    4    5    6
 [4,]    1    2    3    4    5    6    7
 [5,]    2    3    4    5    6    7    8
 [6,]    3    4    5    6    7    8    9
 [7,]    4    5    6    7    8    9   10
 [8,]    5    6    7    8    9   10   11
 [9,]    6    7    8    9   10   11   12
[10,]    7    8    9   10   11   12   13
CJ(1:10, -3:3)[, V3 := V1 + V2][]
    V1 V2 V3
 1:  1 -3 -2
 2:  1 -2 -1
 3:  1 -1  0
 4:  1  0  1
 5:  1  1  2
 ---
66: 10 -1  9
67: 10  0 10
68: 10  1 11
69: 10  2 12
70: 10  3 13
    V1 V2 V3

小数Date

第二个问题更难以追查。它是由OP创建样本数据的方式引起的:

test <- data.table(date=as.Date(Sys.time())+runif(1000,1,365))

runif(1000,1,365)创建double非整数值的向量:

set.seed(3); head(runif(1000,1,365))
[1]  62.16712 294.93597 141.11902 120.29529 220.16465 220.99944

这些值会添加到Date值,该值会创建小数日期。打印时小数部分是不可见的:

as.Date("2018-01-01") + c(0, 0.1)
[1] "2018-01-01" "2018-01-01"

只有将日期转换为numericPOSIXct时才会显而易见:

as.POSIXct(as.Date("2018-01-01") + c(0, 0.1))
[1] "2018-01-01 01:00:00 CET" "2018-01-01 03:23:59 CET"

现在,显而易见的是

中的条件
test[date %in% (as.Date(paste(year,"-06-04",sep="")) + (-3:3)),]

从未找到过匹配。 LHS date始终具有小数部分,而RHS具有integerish值而没有小数部分。根本原因是Date是使用double构建的。请注意,data.table包引入了基于整数的日期类IDate

OP用于创建样本数据的代码有一个简单的解决方法:

set.seed(3)
test <- data.table(date = as.Date(Sys.time()) + as.integer(runif(1000,1,365)))

或者,可以使用Sys.Date()sample.int()

set.seed(3)
test1 <- data.table(date = Sys.Date() + sample.int(365, 1000, TRUE))