R - 检查字符串是否包含特定日期范围内的日期

ash*_*tty 4 r spotfire

我在R脚本中有以下要求(在Spotfire中编写表达式函数):

dateString <- "04/30/2015 03/21/2015 06/28/2015 12/19/2015"
startDate <- "04/01/2015"
endDate <- "07/01/2015"
Run Code Online (Sandbox Code Playgroud)

注意:dateString可以包含任意数量的日期.

如果dateString中的所有日期都在startDate和endDate之间,我需要返回"Yes"/ TRUE,否则返回"No"/ FALSE.

akr*_*run 6

您可以使用便捷的功能between无论从dplyr/data.table转换为"日期"下课.'dateString'是一个单独的字符串,我们可以使用strsplit或仅使用分割在空白处scan.

library(lubridate)
library(data.table)
between(mdy(scan(text=dateString, what='', quiet=TRUE)), 
              mdy(startDate), mdy(endDate))
Run Code Online (Sandbox Code Playgroud)

上面的单行可以分成不同的步骤,以便于理解.

#split the string to substring at whitespace.
v1 <- scan(text=dateString, what='', quiet=TRUE)
#convert to Date class
v2 <- mdy(v1)
#use between to get a logical index of the dates 
#that are between 'startDate' and 'endDate'
res <- between(v2, mdy(startDate), mdy(endDate))
res 
#[1]  TRUE FALSE  TRUE FALSE
Run Code Online (Sandbox Code Playgroud)

为了完整起见,如果我们需要'是/否'值代替'TRUE/FALSE',我们可以使用ifelse.这部ifelse分会更容易理解.如果元素为"TRUE",则将其替换为"Yes",否则将替换为"No".

 ifelse(res, 'Yes', 'No')
 #[1] "Yes" "No"  "Yes" "No" 
Run Code Online (Sandbox Code Playgroud)

或数字索引来替换'res'中的值.

 c('No', 'Yes')[res+1L]
 #[1] "Yes" "No"  "Yes" "No" 
Run Code Online (Sandbox Code Playgroud)

上述步骤可能有点令人困惑.但是,每当我发现不太明显的东西时,我就会将代码分成尽可能小的代码.在这里,我会寻找

 res+1L
 #[1] 2 1 2 1
Run Code Online (Sandbox Code Playgroud)

添加/乘以逻辑索引将逻辑索引强制转换为二进制整数,即0/1.这里我们添加1L或整数1.会发生的是,强制为1的TRUE值将与1L一起添加到2,而强制为0的FALSE将添加1和0+1 = 1.

当逻辑索引转换为数字索引时,我们使用它来替换字符串向量c('No', 'Yes').请注意,在字符串的第一个位置是"否",在第二个位置是"是".根据数字索引的长度,即'4'和该索引指定的位置索引,我们用'是/否'替换索引.


我们也可以不使用任何外部包.

 v2 <- as.Date(v1, '%m/%d/%Y')
 v2 >= as.Date(startDate, '%m/%d/%Y') & v2 <= as.Date(endDate, '%m/%d/%Y')
 #[1]  TRUE FALSE  TRUE FALSE
Run Code Online (Sandbox Code Playgroud)

如果我们不需要考虑'startDate'和'endDate',请替换>=/<=>/<


Sve*_*ein 5

这是一个没有额外包装的替代解决方案.

首先,将字符串表示为日期:

dates <- lapply(strsplit(dateString, " +")[[1L]], as.Date, "%m/%d/%Y")
start <- as.Date(startDate, "%m/%d/%Y")
end <- as.Date(endDate, "%m/%d/%Y")
Run Code Online (Sandbox Code Playgroud)

其次,检查日期是否在开始和结束之间:

sapply(dates, function(x) x >= start && x <= end)
# [1]  TRUE FALSE  TRUE FALSE
Run Code Online (Sandbox Code Playgroud)