【问题标题】:R filtering/selecting data by POSIXct time and a conditionR按POSIXct时间和条件过滤/选择数据
【发布时间】:2018-12-30 04:41:19
【问题描述】:

我在不同的城市树种上以 10 分钟的高时间分辨率测量了温度,应该比较它们的反应。因此,我正在研究特别是高温期。我未能在我的数据集上执行的任务是从最大值中选择完整的天数。例如。一次测量值高于 30°C 的日子应该完全从我的数据框中子集。 您可以在下面找到一个可重现的示例,该示例应该可以说明我的问题:

在我的Measurings 数据框中,我计算了一个列,指示单个测量值是高于还是低于 30°C。我想使用该列来告诉其他函数他们应该选择一天还是不生成New Dataframe。当一天中的任何时间值高于 30°C 时,我希望将其按日期从 00:00 到 23:59 包含在 New Dataframe 中以进行进一步分析。

start <- as.POSIXct("2018-05-18 00:00", tz = "CET")
tseq <- seq(from = start, length.out = 1000, by = "hours")

Measurings <- data.frame(
  Time = tseq,
  Temp = sample(20:35,1000, replace = TRUE),
  Variable1 = sample(1:200,1000, replace = TRUE),
  Variable2 = sample(300:800,1000, replace = TRUE)
)

Measurings$heat30 <- ifelse(Measurings$Temp > 30,"heat", "normal")

Measurings$otheroption30 <- ifelse(Measurings$Temp > 30,"1", "0")

该示例生成了一个与我的数据结构类似的 Dataframe:

head(Measurings)

                 Time Temp Variable1 Variable2 heat30 otheroption30
1 2018-05-18 00:00:00   28        56       377 normal             0
2 2018-05-18 01:00:00   23        65       408 normal             0
3 2018-05-18 02:00:00   29        78       324 normal             0
4 2018-05-18 03:00:00   24       157       432 normal             0
5 2018-05-18 04:00:00   32       129       794   heat             1
6 2018-05-18 05:00:00   25        27       574 normal             0

那么我如何子集化以获得一个 New Dataframe 其中至少有一个条目被指示为“热”的所有天数?

我知道,例如 dplyr:filter 可以过滤单个条目(示例头部的第 5 行)。 但我怎么知道要花一整天 2018-05-18 呢?

我对使用 R 分析数据非常陌生,因此我将不胜感激有关我的问题的有效解决方案的任何建议。 dplyr是我在相当多的任务中一直使用的,但我对任何可行的方法持开放态度。

非常感谢,康拉德

【问题讨论】:

    标签: r datetime dplyr time-series posixct


    【解决方案1】:

    创建指定哪一天的变量(删除小时、分钟等)。迭代唯一的日期,只取那些在 heat30 中至少包含一次“热”的子集:

    Measurings <- Measurings %>% mutate(Time2 = format(Time, "%Y-%m-%d"))
    
    res <- NULL
    newdf <- lapply(unique(Measurings$Time2), function(x){
    
      ss <- Measurings %>% filter(Time2 == x) %>% select(heat30) %>% pull(heat30) # take heat30 vector
      rr <- Measurings %>% filter(Time2 == x) # select date x
    
      # check if heat30 vector contains heat value at least once, if so bind that subset 
      if(any(ss == "heat")){
        res <- rbind(res, rr)
      }
      return(res)
    
    }) %>% bind_rows()
    

    【讨论】:

    • 这个对我来说效果很好,但我想我并不完全理解它。 “ss”和“rr”分别是哪一种对象,它们是如何工作的?
    • ss 是一个包含“热”值的向量。如果 ss 中至少有一个“热”值,那么我们将 rr 附加到 res 数据帧(所有日期都如您指定),否则,继续下一个日期并重复该过程。
    【解决方案2】:

    以下是使用问题中提供的数据集的一种可能解决方案。请注意,这不是一个很好的例子,因为所有的日子可能包括至少一个标记为超过 30 °C 的观察(即在这个数据集中没有日子可以过滤掉,但代码应该这样做实际工作)。

    # import packages
    library(dplyr)
    library(stringr)
    
    # break the time stamp into Day and Hour
    time_df <- as_data_frame(str_split(Measurings$Time, " ", simplify = T))
    
    # name the columns
    names(time_df) <- c("Day", "Hour")
    
    # create a new measurement data frame with separate Day and Hour columns
    new_measurings_df <- bind_cols(time_df, Measurings[-1])
    
    # form the new data frame by filtering the days marked as heat
    new_df <- new_measurings_df %>%
      filter(Day %in% new_measurings_df$Day[new_measurings_df$heat30 == "heat"])
    

    更准确地说,您正在创建一个包含 1000 个观察值的随机样本,该样本在 40 天内的温度变化在 20 到 35 之间。因此,在您的示例中,每天都有至少一个观察值被标记为超过 30 °C。此外,设置种子以确保reproducibility 始终是一个好习惯。

    【讨论】:

    • 这个解决了我的问题,除了我很难再次合并 Day 和 Hour 列以继续使用我的 POSIXct 日期时间,我需要进一步分析。下次我会设置种子并尝试更好地匹配我的数据。
    • @Konrad Bauer,您可以保留 POSIXct 时间戳,稍作修改:bind_cols(time_df, Measurings)
    猜你喜欢
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多