【问题标题】:Add consecutive temp values above threshold to create "degree hours"添加高于阈值的连续温度值以创建“度小时”
【发布时间】:2017-06-01 00:48:54
【问题描述】:

我正在处理每小时温度的数据集,我需要为每个极端事件计算高于热阈值的“度时”。我打算对每个事件的强度(组合大小和持续时间)进行统计,以比较同一时间段内的多个站点。

数据示例:

        Temp 
1     14.026
2     13.714
3     13.25
.....
21189 12.437
21190 12.558
21191 12.703
21192 12.896

仅选择高于 18 度阈值的小时数,然后减去 18 以显示 18 度以上的度数后的数据:

       Temp
5297  0.010
5468  0.010
5469  0.343
5470  0.081
5866  0.010
5868  0.319
5869  0.652

在这一步之后,我需要帮助计算读数超过我指定阈值的连续小时数。

我希望从上面的示例中产生什么:

       Temp
   1  0.010
   2  0.434
   3  0.010
   4  0.971

我曾讨论过如何在时间序列内或通过添加额外的列来处理这些数据,但我不希望每个变暖事件都有多行。我将非常感谢任何建议。

【问题讨论】:

    标签: r dataframe threshold temperature


    【解决方案1】:

    这是基础 R 中的替代解决方案。

    您有一些四处走动的数据,并且您想要总结截止点以上的点。例如:

    set.seed(99999)
    x <- cumsum(rnorm(30))
    plot(x, type='b')
    abline(h=2, lty='dashed')
    

    看起来像这样:

    首先,我们希望根据数据何时跨越分界线将数据分组。我们可以在指标上使用运行长度编码来获得压缩版本:

    x.rle <- rle(x > 2)
    

    其中的值:

    Run Length Encoding
      lengths: int [1:8] 5 2 3 1 9 4 5 1
      values : logi [1:8] FALSE TRUE FALSE TRUE FALSE TRUE ...
    

    第一组是前 5 个点,其中 x > 2 为 FALSE;第二组是以下两点,以此类推。

    我们可以通过替换 rle 对象中的值来创建组 id,然后进行反向转换:

    x.rle$values <- seq_along(x.rle$values)
    group <- inverse.rle(x.rle)
    

    最后,我们按组汇总,只保留截断线以上的数据:

    aggregate(x~group, subset = x > 2, FUN=sum)
    

    产生:

      group            x
    1     2  5.113291213
    2     4  2.124118005
    3     6 11.775435706
    4     8  2.175868979
    

    【讨论】:

      【解决方案2】:

      我会为此使用data.table,当然还有其他方法。

      library( data.table )
      setDT( df )
      temp.threshold <- 18
      

      首先创建一列,显示数据中每个值的上一个值。这将有助于找到温度高于阈值的点。

      df[ , lag := shift( Temp, fill = 0, type = "lag" ) ]
      

      现在使用之前的值列与Temp 列进行比较。将温度上升到阈值以上的每个点标记为 1,将所有其他点标记为 0。

      df[ , group := 0L 
          ][ Temp > temp.threshold & lag <= temp.threshold, group := 1L ]
      

      现在我们可以获得该新列的cumsum,它将在温度升至阈值以上后为每个序列提供其自己的group ID。

      df[ , group := cumsum( group ) ]
      

      现在我们可以去掉所有不超过阈值的值。

      df <- df[ Temp > temp.threshold, ]
      

      并通过查找每个“组”的“学位小时数”来总结剩下的内容。

      bygroup <- df[ , sum( Temp - temp.threshold ), by = group ]
      

      我稍微修改了您的输入数据,以提供一些数据超过阈值的测试事件:

      structure(list(num = c(1L, 2L, 3L, 4L, 5L, 21189L, 21190L, 21191L, 
      21192L, 21193L, 21194L), Temp = c(14.026, 13.714, 13.25, 20, 
      19, 12.437, 12.558, 12.703, 12.896, 21, 21)), class = c("tbl_df", 
      "tbl", "data.frame"), row.names = c(NA, -11L), .Names = c("num", 
      "Temp"), spec = structure(list(cols = structure(list(num = structure(list(), class = c("collector_integer", 
      "collector")), Temp = structure(list(), class = c("collector_double", 
      "collector"))), .Names = c("num", "Temp")), default = structure(list(), class = c("collector_guess", 
      "collector"))), .Names = c("cols", "default"), class = "col_spec"))
      

      有了这些数据,这是上面代码的输出(注意$V1 是“度小时”):

      > bygroup
         group V1
      1:     1  3
      2:     2  6
      

      【讨论】:

        猜你喜欢
        • 2020-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-22
        相关资源
        最近更新 更多