R - 检查字符串是否包含特定日期范围内的日期
R - check if string contains dates within specific date range
我在 R 脚本中有以下要求(在 Spotfire 中编写表达式函数):
dateString <- "04/30/2015 03/21/2015 06/28/2015 12/19/2015"
startDate <- "04/01/2015"
endDate <- "07/01/2015"
注意:dateString 可以包含任意数量的日期。
如果 dateString 中的所有日期都在 startDate 和 endDate 之间,我需要 return "Yes"/TRUE,否则 return "No"/FALSE。
在转换为 'Date' class 后,您可以使用来自 dplyr/data.table
的便捷函数 between
。 'dateString' 是单个字符串,我们可以使用 strsplit
或仅使用 scan
.
在白色 space 处拆分它
library(lubridate)
library(data.table)
between(mdy(scan(text=dateString, what='', quiet=TRUE)),
mdy(startDate), mdy(endDate))
为了便于理解,可以将上面的单行拆分成不同的步骤。
#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
为了完整起见,如果我们需要 'Yes/No' 值代替 'TRUE/FALSE',我们可以使用 ifelse
。 ifelse
部分会更容易理解。如果元素是 'TRUE',它将被替换为 'Yes',否则它将被替换为 'No'。
ifelse(res, 'Yes', 'No')
#[1] "Yes" "No" "Yes" "No"
或用数字索引替换'res'中的值。
c('No', 'Yes')[res+1L]
#[1] "Yes" "No" "Yes" "No"
上面的步骤可能有点混乱。但是,每当我发现一些不太明显的东西时,我都会将代码拆分成尽可能小的代码。在这里,我会寻找
res+1L
#[1] 2 1 2 1
adding/multiplying 逻辑索引将逻辑索引强制为二进制整数,即 0/1。这里我们添加了 1L
或整数 1。发生的情况是,强制为 1 的 TRUE 值将与 1L 相加以获得 2,而强制为 0 的 FALSE 值将与 1 和 0+1 = 1
.[= 相加27=]
由于逻辑索引被转换为数字索引,我们用它来替换字符串向量c('No', 'Yes')
。请注意,字符串的第一个位置是 'No',第二个位置是 'Yes'。根据数字索引的长度,即“4”和该索引指定的位置索引,我们将索引替换为 'Yes/No'。
我们也可以不使用任何外部包。
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
如果我们不需要考虑 'startDate' 和 'endDate',请将 >=/<=
替换为 >/<
这是一个没有额外包的替代解决方案。
首先,将字符串表示为日期:
dates <- lapply(strsplit(dateString, " +")[[1L]], as.Date, "%m/%d/%Y")
start <- as.Date(startDate, "%m/%d/%Y")
end <- as.Date(endDate, "%m/%d/%Y")
其次,检查日期是否在开始和结束之间:
sapply(dates, function(x) x >= start && x <= end)
# [1] TRUE FALSE TRUE FALSE
我在 R 脚本中有以下要求(在 Spotfire 中编写表达式函数):
dateString <- "04/30/2015 03/21/2015 06/28/2015 12/19/2015"
startDate <- "04/01/2015"
endDate <- "07/01/2015"
注意:dateString 可以包含任意数量的日期。
如果 dateString 中的所有日期都在 startDate 和 endDate 之间,我需要 return "Yes"/TRUE,否则 return "No"/FALSE。
在转换为 'Date' class 后,您可以使用来自 dplyr/data.table
的便捷函数 between
。 'dateString' 是单个字符串,我们可以使用 strsplit
或仅使用 scan
.
library(lubridate)
library(data.table)
between(mdy(scan(text=dateString, what='', quiet=TRUE)),
mdy(startDate), mdy(endDate))
为了便于理解,可以将上面的单行拆分成不同的步骤。
#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
为了完整起见,如果我们需要 'Yes/No' 值代替 'TRUE/FALSE',我们可以使用 ifelse
。 ifelse
部分会更容易理解。如果元素是 'TRUE',它将被替换为 'Yes',否则它将被替换为 'No'。
ifelse(res, 'Yes', 'No')
#[1] "Yes" "No" "Yes" "No"
或用数字索引替换'res'中的值。
c('No', 'Yes')[res+1L]
#[1] "Yes" "No" "Yes" "No"
上面的步骤可能有点混乱。但是,每当我发现一些不太明显的东西时,我都会将代码拆分成尽可能小的代码。在这里,我会寻找
res+1L
#[1] 2 1 2 1
adding/multiplying 逻辑索引将逻辑索引强制为二进制整数,即 0/1。这里我们添加了 1L
或整数 1。发生的情况是,强制为 1 的 TRUE 值将与 1L 相加以获得 2,而强制为 0 的 FALSE 值将与 1 和 0+1 = 1
.[= 相加27=]
由于逻辑索引被转换为数字索引,我们用它来替换字符串向量c('No', 'Yes')
。请注意,字符串的第一个位置是 'No',第二个位置是 'Yes'。根据数字索引的长度,即“4”和该索引指定的位置索引,我们将索引替换为 'Yes/No'。
我们也可以不使用任何外部包。
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
如果我们不需要考虑 'startDate' 和 'endDate',请将 >=/<=
替换为 >/<
这是一个没有额外包的替代解决方案。
首先,将字符串表示为日期:
dates <- lapply(strsplit(dateString, " +")[[1L]], as.Date, "%m/%d/%Y")
start <- as.Date(startDate, "%m/%d/%Y")
end <- as.Date(endDate, "%m/%d/%Y")
其次,检查日期是否在开始和结束之间:
sapply(dates, function(x) x >= start && x <= end)
# [1] TRUE FALSE TRUE FALSE