select 按日期范围和标识符有条件地 data.table 多个项目
Conditionally select multiple items by date range and identifier in data.table
我有一个 data.table
包含单位标识符、设置标识符和此设置有效的数据范围。我需要提取特定日期的特定单位标识符的设置。以下最小工作示例显示了我将如何获得结果。
library(data.table)
settingstable=data.table(UNITID=c(1,1,1,2,2,2,3,4,5,6,6),
STARTDATE=as.POSIXct(c("2018-01-01","2018-02-28","2018-06-01","2018-01-01","2018-04-01","2018-06-01","2018-01-01","2018-01-01","2018-01-01","2018-01-01","2018-05-01")),
ENDDATE=as.POSIXct(c("2018-02-28","2018-05-31","2018-12-31","2018-03-31","2018-05-31","2018-12-31","2018-12-31","2018-12-31","2018-12-31","2018-04-30","2018-12-31")),
SETTINGS=c(1,2,3,4,5,6,7,8,9,10,11))
selectunits=c(2,4,6)
selectdays=as.POSIXct(c("2018-04-02","2018-05-03","2018-02-01"))
resultsettings=NULL
for (i in 1:length(selectunits)) {
resultsettings=rbind(resultsettings,settingstable[UNITID==selectunits[i] & STARTDATE <= selectdays[i] & ENDDATE >= selectdays[i],.(UNITID,SETTINGS)])
}
对于大 data.tables 或大量的单位和天数,这将是非常低效的。我希望用 by=UNITID
进行分组会起作用,但不幸的是这是不可能的,因为以下将导致 longer object length is not a multiple of shorter object length
错误。
resultsettings=settingstable[UNITID %in% selectunits & STARTDATE <= selectdays & ENDDATE >= selectdays,.(UNITID,SETTINGS),by=UNITID]
如何改进我的代码以使其运行更高效?
您可以使用非等连接:
settingstable[.(u = selectunits, d = selectdays),
on=.(UNITID = u, STARTDATE <= d, ENDDATE >= d),
.(UNITID, SETTINGS)]
UNITID SETTINGS
1: 2 5
2: 4 8
3: 6 10
语法为x[i, on=, j]
。
- 列表
i = .(u = selectunits, d = selectdays)
被视为 table,将加入 x = settingstable
。
- 如果
i
in x
根据 on=
. 查找每一行,则连接工作
- 在
j
中,我们可以对结果进行改造。 (如果没有 j
,我们只会得到加入的 table。)
如果您的 on=
条件产生多个匹配项,它们将全部出现在结果中。如果他们没有留下任何匹配项,SETTINGS
和 x
中的其他列将是 NA(尽管这可以使用 nomatch=
参数进行调整)。
我有一个 data.table
包含单位标识符、设置标识符和此设置有效的数据范围。我需要提取特定日期的特定单位标识符的设置。以下最小工作示例显示了我将如何获得结果。
library(data.table)
settingstable=data.table(UNITID=c(1,1,1,2,2,2,3,4,5,6,6),
STARTDATE=as.POSIXct(c("2018-01-01","2018-02-28","2018-06-01","2018-01-01","2018-04-01","2018-06-01","2018-01-01","2018-01-01","2018-01-01","2018-01-01","2018-05-01")),
ENDDATE=as.POSIXct(c("2018-02-28","2018-05-31","2018-12-31","2018-03-31","2018-05-31","2018-12-31","2018-12-31","2018-12-31","2018-12-31","2018-04-30","2018-12-31")),
SETTINGS=c(1,2,3,4,5,6,7,8,9,10,11))
selectunits=c(2,4,6)
selectdays=as.POSIXct(c("2018-04-02","2018-05-03","2018-02-01"))
resultsettings=NULL
for (i in 1:length(selectunits)) {
resultsettings=rbind(resultsettings,settingstable[UNITID==selectunits[i] & STARTDATE <= selectdays[i] & ENDDATE >= selectdays[i],.(UNITID,SETTINGS)])
}
对于大 data.tables 或大量的单位和天数,这将是非常低效的。我希望用 by=UNITID
进行分组会起作用,但不幸的是这是不可能的,因为以下将导致 longer object length is not a multiple of shorter object length
错误。
resultsettings=settingstable[UNITID %in% selectunits & STARTDATE <= selectdays & ENDDATE >= selectdays,.(UNITID,SETTINGS),by=UNITID]
如何改进我的代码以使其运行更高效?
您可以使用非等连接:
settingstable[.(u = selectunits, d = selectdays),
on=.(UNITID = u, STARTDATE <= d, ENDDATE >= d),
.(UNITID, SETTINGS)]
UNITID SETTINGS
1: 2 5
2: 4 8
3: 6 10
语法为x[i, on=, j]
。
- 列表
i = .(u = selectunits, d = selectdays)
被视为 table,将加入x = settingstable
。 - 如果
i
inx
根据on=
. 查找每一行,则连接工作
- 在
j
中,我们可以对结果进行改造。 (如果没有j
,我们只会得到加入的 table。)
如果您的 on=
条件产生多个匹配项,它们将全部出现在结果中。如果他们没有留下任何匹配项,SETTINGS
和 x
中的其他列将是 NA(尽管这可以使用 nomatch=
参数进行调整)。