data.table中的Interval类

时间:2018-02-01 20:44:35

标签: r data.table lubridate

我的问题将在以下可重复的例子中解释。

首先,让我们加载所需的包并创建一个POSIXct和一个data.table对象。

library(data.table)
library(lubridate)

target_date <- ymd(20180601, tz='America/Montreal')

test <- data.table(
  V1 = seq(1:3),
  V2 = c(ymd(20170421, tz='America/Montreal'),
         ymd(20170702, tz='America/Montreal'),
         ymd(20180113, tz='America/Montreal'))
)

如下所示,一切正常。

test[]

##     V1         V2
##  1:  1 2017-04-21
##  2:  2 2017-07-02
##  3:  3 2018-01-13

然后,我创建一个包含Interval个对象的新列。

test[, V3:=interval(V2, target_date)]

仍然存在,一切都很好。

test[]

##     V1         V2                             V3
##  1:  1 2017-04-21 2017-04-21 EDT--2018-06-01 EDT
##  2:  2 2017-07-02 2017-07-02 EDT--2018-06-01 EDT
##  3:  3 2018-01-13 2018-01-13 EST--2018-06-01 EDT

然后,我想创建两个新列,它们只在前两行定义:第一行是POSIXct列的函数,第二行是{{1}的函数}专栏。

Interval

此时仍然正确。

然后,当我使用test[c(1, 3), V4 := V2 + days(20)] test[] ## V1 V2 V3 V4 ## 1: 1 2017-04-21 2017-04-21 EDT--2018-06-01 EDT 2017-05-11 ## 2: 2 2017-07-02 2017-07-02 EDT--2018-06-01 EDT <NA> ## 3: 3 2018-01-13 2018-01-13 EST--2018-06-01 EDT 2018-02-02 列的列函数尝试相同的操作时,我得到以下Interval

warning

这个test[c(1, 3), V5 := ymd(20180101, tz='America/Montreal') %within% V3] ## Warning messages: ## 1: In as.numeric(a) - as.numeric(b@start) <= b@.Data : ## longer object length is not a multiple of shorter object length ## 2: In `[.data.table`(test, c(1, 3), `:=`(V5, ymd(20180101, tz = "America/Montreal") %within% : ## Supplied 3 items to be assigned to 2 items of column 'V5' (1 unused) 告诉我,实际上,该命令产生了3个值,并且我尝试在2行warning中输入这些值(过滤的data.table有两行)。

我试图弄清问题是什么,我想我发现了一个提示。请考虑以下两个命令:

data.table

事实上,我认为这两个命令会产生相同的结果,但事实并非如此。更令人惊讶的是,它们的test[, V3][2] ## [1] 2017-07-02 EDT--2018-06-01 EDT test[2, V3] ## [1] 2017-04-21 EDT--2018-03-21 EDT 2017-07-02 EDT--2018-06-01 EDT 2018-01-13 EST--2018-12-13 EST 均为1(当查看上面的输出时,我认为第二个命令的length为3)。

length

问题是,这两个命令在length(test[, V3][2]) ## [1] 1 length(test[2, V3]) ## [1] 1 插槽中生成一个向量为1的对象(我猜的是.Data的长度),

Interval

但第一个在test[, V3][2]@.Data ## [1] 28857600 test[2, V3]@.Data ## [1] 28857600 广告位中的向量为1,而第二个广告在start广告位中的向量为3。

start

我知道我可以通过将每个test[, V3][2]@start ## [1] "2017-07-02 EDT" test[2, V3]@start ## [1] "2017-04-21 EDT" "2017-07-02 EDT" "2018-01-13 EST" 对象封装在一个列表中来解决这个问题,并在每次需要时提取它们,但还有其他方法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

可能有点肮脏,但你可以去吧:

test[c(1, 3), V5 := ymd(20180101, tz='America/Montreal') %within% V3[.I]]

test[, dat := (V3[.I]@.Data)]