【问题标题】:Extracting subset of data.table based on date around a given day of the year根据一年中给定日期的日期提取data.table的子集
【发布时间】:2014-06-04 21:13:31
【问题描述】:

我有一个这样的数据表:

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)),]

有什么想法吗??

【问题讨论】:

  • 仅供参考,data.table 有自己的日期操作函数,您只需执行 test[, year := year(date)] 即可创建 year 变量
  • 是的..你可能想看看as.IDate然后你可以使用between函数
  • 感谢@DavidArenburg 和@Mike.Gahan!如果能有一个所有功能的完整列表就好了!

标签: r date data.table


【解决方案1】:

我不认为我完全理解这个问题......但这有帮助吗?无论年份如何,您似乎都希望在今天的 3 天内进行所有观察?

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

【讨论】:

  • 这解决了问题,但我仍然无法理解为什么我的代码不起作用!
【解决方案2】:

OP 有 asked for an explanation 为什么他的两种方法“不起作用”以及为什么第三种方法会发出警告。

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

需要调查的问题

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

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

此外,前两种方法不会遇到错误情况,而只返回一个

2 列的空 data.table(0 行):日期、年份

警告信息说明

在所有三种方法中,OP 通过将长度为 1000 的向量(例如 as.Date(paste(year,"-06-04",sep="")))与长度为 7 的向量 (-3:3) 组合来创建 %in% 运算符的 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))

【讨论】:

    猜你喜欢
    • 2020-05-10
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    相关资源
    最近更新 更多