【问题标题】:Identify only the first matching record仅识别第一个匹配记录
【发布时间】:2014-01-31 22:13:28
【问题描述】:

我有大量时间序列数据存储在一个名为“Tag.data”的数据框中,在几个月的时间里,每 30 秒记录一条记录。例如:

  • 2013-09-30 23:59:00
  • 2013-09-30 23:59:30
  • 2013-10-01 00:00:00
  • 2013-10-01 00:00:30
  • 2013-10-01 00:01:00
  • 2013-10-01 00:01:30
  • 2013-10-01 00:02:00
  • ...
  • 2013-10-15 05:00:00
  • 2013-10-15 05:00:30
  • 2013-10-15 05:01:00
  • 2013-10-15 05:01:30
  • 2013-10-15 05:02:00
  • ...

此数据存储在 Tag.data$dt 中。

在我的数据中,我想确定每个月的第 1 天和第 15 天,以便在以后的绘图中使用它们。

我成功地用这个代码识别了每个月的第一天:

locs <- tapply (X=Tag.data$dt, FUN=min, INDEX=format(Tag.data$dt, '%Y%m'))
at <- Tag.data$dt %in% locs
at <- at & format(Tag.data$dt, '%m') %in% c('01', '02', '03','04', '05', '06','07', '08', '09','10', '11', '12') & format(Tag.data$dt, '%d') == '01'

不幸的是,当我尝试使用以下代码识别每个月的第 15 天时,我不太成功:

locs <- tapply (X=Tag.data$dt, FUN=min, INDEX=format(Tag.data$dt, '%Y%m'))
at <- Tag.data$dt %in% locs
at <- at & format(Tag.data$dt, '%m') %in% c('01', '02', '03','04', '05', '06','07', '08', '09','10', '11', '12') & format(Tag.data$dt, '%d') == '01'| 
format(Tag.data$dt, '%m') %in% c('01', '02', '03','04', '05', '06','07', '08', '09','10', '11', '12') & format(Tag.data$dt, '%d') == '15'

虽然这确实标识了每个月的第 1 天和第 15 天,但由于某种原因,它仅标识了该月 1 天的一条记录,但每个月的第 15 天的记录(其中有很多许多)。我只想确定每个月的第 1 天和第 15 天的第一条记录。任何帮助将不胜感激。

【问题讨论】:

    标签: r date datetime


    【解决方案1】:

    从你的代码来看:

    locs <- tapply (X=Tag.data$dt, FUN=min, INDEX=format(Tag.data$dt, '%Y%m'))
    

    我假设 Tag.data$dt 被存储为 POSIX 类之一。

    我只想确定每个月的第 1 天和第 15 天的第一条记录。

    可能很慢,但这确实有效。

    ymd <- format(Tag.data$dt,"%Y%m%d")
    index.01.15 <- !duplicated(ymd) & grepl("01$|15$", ymd)
    

    您可以使用逻辑向量来选择行Tag.data[index.01.15, ]

    【讨论】:

    • 太棒了!这完美地工作并且非常简洁。非常感谢!
    【解决方案2】:

    试试这个。它利用润滑脂。您可以选择日期为 1 或 15 的所有行。

    library(lubridate)
    options(stringsAsFactors=FALSE)
    
    Tag.data = structure(list(dt = c("30/09/2013 23:59", "1/10/2013 0:00", "1/10/2013 0:00", 
    "1/10/2013 0:01", "1/10/2013 0:01", "1/10/2013 0:02", "2/10/2013 0:04", 
    "15/10/2013 5:00", "15/10/2013 5:00", "15/10/2013 5:01", "15/10/2013 5:01", 
    "15/10/2013 5:02")), .Names = "dt", class = "data.frame", row.names = c(NA, 
    -12L))
    
    
    Tag.data$dt = parse_date_time(Tag.data$dt, '%d/%m/%Y %H%M')
    at = Tag.data[day(Tag.data$dt) %in% c(1,15), ]
    

    这更加灵活,因为您可以指定您希望子集化的任何一天。例如,将 c(1,15) 中的值替换为任何一天,或者将 month(Tag.data$dt) %in% c(&lt;INSERT MONTH NUMBER&gt;) 中的值替换为月份的子集。

    【讨论】:

    • 也许 OP 需要进一步处理过去的识别...我会生成一个带有所需标记的数组,然后使用 match 来查找行索引。我希望时间戳不存储为字符串
    【解决方案3】:

    您的数据似乎已经存储为某种日期(例如,POSIXct)。像这样,但行数更多?

    Tag.data <- data.frame(dt=seq(ISOdate(2013,10,1), by = "30 min", length.out = 10000))
    

    然后,如果您只想要第 1 天或第 15 天的第一条记录,这可能会起作用:

    daychars <- format(Tag.data$dt, '%d')
    day1or15 <- daychars %in% c("01","15")
    newday <- c(TRUE, (daychars[1:(length(daychars)-1)] != daychars[2:length(daychars)]))
    format(Tag.data[day1or15 & newday,"dt"],"%m/%d/%Y %H:%M:%S")
    

    newday 行不要求一天从任何特定时间开始,但它确实假定您的时间序列是有序的。

    【讨论】:

      【解决方案4】:

      我建议你使用优秀的xts 包来处理R 中的时间序列数据。

      你没有提供可重复的数据,所以我自己做了一些。

      require(xts)
      Tag.data <- xts(rnorm(1e5), order.by = Sys.time() + seq(30, 3e6, 30))
      

      按月的天子设置是一个简单的单行。

      days_1n15 <- Tag.data[.indexmday(Tag.data) %in% c(1, 15)]
      

      这将返回任何一个月的第 1 天和第 15 天的所有记录。

      现在我们只需要在每个匹配日提取第一个观察结果。

      firstOf <- do.call(rbind, lapply(split(days_1n15, 'days'), first))
      

      其中包含你想要的数据:

      R> firstOf
                               [,1]
      2014-02-01 21:29:01  1.284222
      2014-02-15 00:00:01 -1.262235
      2014-03-01 00:00:01 -0.465001
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-08
        • 1970-01-01
        • 2015-05-21
        • 2012-12-13
        • 2014-03-03
        • 1970-01-01
        • 2021-11-26
        • 1970-01-01
        相关资源
        最近更新 更多