【问题标题】:How do I assign a value in R if within a certain range of time?如果在一定的时间范围内,如何在 R 中赋值?
【发布时间】:2015-08-11 18:48:03
【问题描述】:

我有一个大型数据集,每天从人们那里收集多个数据点。我的 R 数据集包含参与者的响应和响应的时间戳。我想重新编码时间戳以反映他们响应的订单提示。所以基本上,我想根据时间范围为时间戳分配一个值。因此,如果在星期一,响应介于 10:00 和 10:30 之间,我希望值为 1。如果响应介于 12:15 和 12:45 之间,我希望值为 2。如果响应落在在 2:20 到 2:50 之间,我希望值为 3。

但我需要该代码仅适用于星期一的数据。对于周二的数据,时间戳范围会发生变化。例如,如果星期二的响应介于 9:10 和 9:40 之间,则该值应为 1。以此类推。

我一生都无法通过 if else 语句来解决这个问题。当我将时间写入 R 时,它认为我正在为一系列值(10 到 30)而不是时间(10:30)编写代码。

我所拥有的示例:

我想要的示例:(请参阅新的提示栏) 因此,对于 15 年 10 月 11 日,我希望提示 1 介于 11:15:00 和 11:45:00 之间,但对于 15 年 11 月 11 日,我希望提示 1 有所不同——介于 12:00:00 和 12 之间:30:00

【问题讨论】:

标签: r if-statement


【解决方案1】:

如果您想处理时间和日期,POSIXlt 类很有帮助。如果您的时间戳是 存储为字符串,第一步是将它们转换为 POSIXlt。您可以为此使用“strptime”,例如

> t <- strptime("2015-01-01 12:18",format="%Y-%m-%d %H:%M")
> t
[1] "2015-01-01 12:18:00 CET"
> class(t)
[1] "POSIXlt" "POSIXt" 
>

下面的函数“timerange”为这样一个POSIXlt对象分配一个时间范围号:

R <- list( Sun = list(),
           Mon = list( c("10:00","10:30"), c("12:15","12:40"), c("13:15","13:40") ),                      
           Tue = list( c( "9:10", "9:40"), c("11:00","11:30"), c("13:15","13:40") ),
           Wed = list( c("10:00","10:30"), c("12:15","12:40"), c("13:15","13:40") ),                      
           Thu = list( c("10:00","10:30"), c("12:15","12:40"), c("13:15","13:40") ),                      
           Fri = list( c("10:00","10:30"), c("12:15","12:40"), c("13:15","13:40") ),                      
           Sat = list( c("10:00","10:30"), c("12:15","12:40"), c("13:15","13:40") )  )                      

timerange <- function(t)
{
  s <- unlist(strsplit(strftime(t,format="%Y-%m-%d %H:%M:%S %w")," "))  
  w <- as.numeric(s[3]) + 1  
  n <- sapply(R[[w]], function(x){ strptime(paste(s[1]," ",x,":00",sep=""),
                                            format="%Y-%m-%d %H:%M:%S")})  

  return( which(sapply(n,function(x){ t-x[1]>=0 & t-x[2]<=0})) )
}

“R”是所有时间范围的列表。你可以随意改变它。 "strftime" 是 "strptime" 的对应物,即将 POSIXlt 对象 "t" 转换为 所需格式的字符串。然后将这个字符串吐到日期部分,时间部分, 和星期几。后者用于在“R”中选择适当的子列表。 然后“strptime”用于创建成对的 POSIXlt 对象列表。时间部分来自 “R”的适当子列表,日期部分来自“t”。每个这样的对代表一个时间间隔。 那么时间范围号就是包含“t”的时间区间的索引。

一些例子:

> t <- strptime("2015-01-01 12:18",format="%Y-%m-%d %H:%M")
> timerange(t)
[1] 2
> t <- strptime("2015-01-05 10:01",format="%Y-%m-%d %H:%M")
> timerange(t)
[1] 1
> t <- strptime("05.01.2015 13:25",format="%d.%m.%Y %H:%M")
> timerange(t)
[1] 3

【讨论】:

    【解决方案2】:

    我有一个更简单的解决方案,它使用天、小时和分钟以及您可以用作函数的(手动)过滤器。 检查我的简单示例:

     library(lubridate)
    
       # example dataset
       dt = data.frame(responce = 1:3,
                       date = c("2015-08-10 10:15:34","2015-08-10 12:29:14","2015-08-11 09:12:18"),
                          stringsAsFactors = F)
    
         dt
    
    #   responce                date
    #   1        1 2015-08-10 10:15:34
    #   2        2 2015-08-10 12:29:14
    #   3        3 2015-08-11 09:12:18
    
    
         # transform to date and obtain day, hour and minutes
       dt$date = ymd_hms(dt$date)
       dt$day = wday(dt$date, label=T)
       dt$hour = hour(dt$date)
       dt$minute = minute(dt$date)
    
         dt
    
    #   responce                date  day hour minute
    #   1        1 2015-08-10 10:15:34  Mon   10     15
    #   2        2 2015-08-10 12:29:14  Mon   12     29
    #   3        3 2015-08-11 09:12:18 Tues    9     12
    
    
         # create a column with an arbitrary value to start with and also double check in the end
       dt$value = -1
    
         # conditions for Monday
       dt$value[dt$day=="Mon" & dt$hour==10 & dt$minute >= 0 & dt$minute <=30] = 1
       dt$value[dt$day=="Mon" & dt$hour==12 & dt$minute >= 15 & dt$minute <=45] = 2
       dt$value[dt$day=="Mon" & dt$hour==14 & dt$minute >= 20 & dt$minute <=50] = 3
    
         # conditions for Tuesday
       dt$value[dt$day=="Tues" & dt$hour==9 & dt$minute >= 10 & dt$minute <=40] = 1
    
         dt
    
    #   responce                date  day hour minute value
    #   1        1 2015-08-10 10:15:34  Mon   10     15     1
    #   2        2 2015-08-10 12:29:14  Mon   12     29     2
    #   3        3 2015-08-11 09:12:18 Tues    9     12     1
    
         # double check all your rows matched (you have no -1 values)
       dt[dt$value == -1]
    
      # data frame with 0 columns and 3 rows
    

    【讨论】:

    • 这行得通!非常感谢@AntoniosK! (我知道超级延迟,我对 R 感到非常沮丧并逃离了一段时间)我正在发布我最终所做的完整代码。
    【解决方案3】:

    我最终使用了其中一些答案。

    library(lubridate)
    
    #change data to POSIXct class
    data$StartDate <- dmy(as.character(data$StartDate))
    data$EndDate <- dmy(as.character(data$EndDate))
    
    data$StartTime2 <- hms(as.character(data$StartTime))
    data$EndTime2 <- hms(as.character(data$Endataime))
    

    我不必两者都做,但我还是做了。我创建了一个附加变量,因为更改它会使它看起来很有趣。

    #check me out
    class(data$StartDate)
    #[1] "POSIXct" "POSIXt" 
     class(data$StartTime2)
    #[1] "Period"
    #attr(,"package")
    #[1] "lubridate"
    

    根据我随后所做的第二条评论:

    data$day = wday(data$StartDate, label=T)
    data$hour = hour(data$StartTime2)
    data$minute = minute(data$StartTime2)
    
    # create a column with an arbitrary value to start with and also double     check in the end
    data$prompt = -1
    
    # conditions for Tuesday (10/11/2015) 
    data$prompt[data$day=="Tues" & data$hour==11 & data$minute >= 10 & data$minute <=40] = 1
    data$prompt[data$day=="Tues" & data$hour==13 & data$minute >= 35 & data$minute <=59] = 2
    data$prompt[data$day=="Tues" & data$hour==16 & data$minute >= 15 & data$minute <=45] = 3
    

    等等。我知道我必须为这一天修复提示 2,因为它进入第 14 小时,但这是接下来要玩的。谢谢你的帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-12
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 2022-12-22
      • 1970-01-01
      • 2019-05-27
      • 2019-04-29
      相关资源
      最近更新 更多