检查是否有数值在指定范围内

3

我有一组观测数据,其中包含了响应事件的日期。

structure(list(Date1_P2 = structure(c(14061, 14944, 14944), class = "Date"), 
    Date2_P2 = structure(c(NA, 11566, 11747), class = "Date"), 
    Date3_P2 = structure(c(NA, 10408, 11627), class = "Date"), 
    Date4_P2 = structure(c(NA, 8370, 11566), class = "Date")), .Names = c("Date1_P2", 
"Date2_P2", "Date3_P2", "Date4_P2"), row.names = c(NA, 3L), class = "data.frame")
> dates
    Date1_P2   Date2_P2   Date3_P2   Date4_P2
1 2008-07-01       <NA>       <NA>       <NA>
2 2010-12-01 2001-09-01 1998-07-01 1992-12-01
3 2010-12-01 2002-03-01 2001-11-01 2001-09-01

我想创建一个变量,在触发事件的时间范围之内,如果任何日期都落在这个范围内,那么该变量为TRUE。比如说,2001年9月发生了一些事情,观察结果可能会对此作出反应或者预测。我写了以下函数:

checkmove <- function(event, range, moves){
  moves <- as.numeric(moves)
  early <- as.numeric(event - range)
  late  <- as.numeric(event + range)
  moved <- any(moves > early & moves < late, na.rm=TRUE) 
  return(moved)
}

如果事件发生的180天之内有任何一方做出响应,则该值应为TRUE。该函数逐行处理,但我无法使其在整个表格上工作。

# This is right
> checkmove(as.Date("2001-09-01"), 180, dates[1,])
[1] FALSE
> checkmove(as.Date("2001-09-01"), 180, dates[2,])
[1] TRUE
> checkmove(as.Date("2001-09-01"), 180, dates[3,])
[1] TRUE
# This is wrong
> apply(dates, 1, function(x) checkmove(as.Date("2001-09-01"), 180, x))
    1     2     3 
FALSE FALSE FALSE 
Warning messages:
1: In checkmove(as.Date("2001-09-01"), 180, x) :
  NAs introduced by coercion
2: In checkmove(as.Date("2001-09-01"), 180, x) :
  NAs introduced by coercion
3: In checkmove(as.Date("2001-09-01"), 180, x) :
  NAs introduced by coercion

我是否没有使用正确的apply函数?我真的很想避免使用for循环。有没有更好的方法来解决这个问题?

1个回答

3
是的,apply将数据框dates强制转换为类matrix。因此,这些值不再是date类,而是character类。因此,as.numeric无法正常工作(由于强制转换引入了NAs)。
> dates
    Date1_P2   Date2_P2   Date3_P2   Date4_P2
1 2008-07-01       <NA>       <NA>       <NA>
2 2010-12-01 2001-09-01 1998-07-01 1992-12-01
3 2010-12-01 2002-03-01 2001-11-01 2001-09-01
> apply(dates, 1, function(x) class(x))
          1           2           3 
"character" "character" "character" 

尝试使用plyr包中的“ddply”系列。例如:
> library(plyr)
> aaply(dates, 1, function(x) checkmove(as.Date("2001-09-01"), 180, x), .expand=F)
    1     2     3 
FALSE  TRUE  TRUE 

很好。我觉得baseplyr应用函数之间的分歧是R语言中最大的障碍之一。 - gregmacfarlane
@gmacfarlane 的 plyr 函数更加“用户友好”(特别是在提供多种输入/输出数据类型方面)。如果需要/想要“基本”解决方案,则可以使用以下方法:1)for 循环,2)在 apply 之前将其转换为数字,3)在 apply 内部将其转换为日期然后再转回数字(这会更慢,但仍然是一个有效的选项)。 - Michele

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接