【问题标题】:convert a irregular time series of a data table with factors into a regular time series in R将带有因子的数据表的不规则时间序列转换为R中的规则时间序列
【发布时间】:2020-09-21 00:56:38
【问题描述】:

我正在尝试将数据表的不规则时间序列转换为规则时间序列。我的数据是这样的

library(data.table)
dtRes <- data.table(time  = c(0.1, 0.8, 1, 2.3, 2.4, 4.8, 4.9),
                    abst  = c(1, 1, 1, 0, 0, 3, 3),
                    farbe = as.factor(c("keine", "keine", "keine", "keine", "keine", "rot", "blau")),
                    gier  = c(2.5, 2.5, 2.5, 0, 0, 3, 3),
                    goff  = as.factor(c("haus", "maus", "toll", "maus", NA, "maus", "maus")),
                    huft  = as.factor(c(NA, NA, NA, "wolle", "wolle", "holz", "holz")),
                    mode  = c(4, 4, 4, 2.5, NA, 3, 3))

如何通过大约 1 秒的块大小以块的形式聚合观察结果? (行数可变 - 如果 1 秒内没有行,则为 0)结果应该是数字列的平均值(省略 NA),如果有超过 1 个唯一行,则结果应该是整个重复行的因子价值。如果这对于因子是不可能的或对您没有意义,也可以只取因子列中特定第二个的第一个值。这样,它将是真正的常规时间序列,没有任何重复的时间。如果间隔没有值(如示例中的第 2 秒),则结果为 NA。

最终结果可能如下所示(取决于是否重复行):

有重复:

wiDups <- data.table(time  = c(1, 1, 2, 3, 4, 5, 5),
                     abst  = c(1, 1, NA, 1, NA, 5, 5),
                     farbe = as.factor(c("keine", "keine", NA, "keine", NA, "rot", "blau")),
                     gier  = c(2.5, 2.5, NA, 0, NA, 4.5, 4.5),
                     goff  = as.factor(c("haus", "maus", NA, "maus", NA, "maus", "maus")),
                     huft  = as.factor(c(NA, NA, NA, "wolle", NA, "holz", "holz")),
                     mode  = c(5, 5, NA, 2.5, NA, 4, 4))

并且没有重复:

noDups <- data.table(time  = c(1, 2, 3, 4, 5),
                     abst  = c(1, NA, 1, NA, 5),
                     farbe = as.factor(c("keine", NA, "keine", NA, "rot")),
                     gier  = c(2.5, NA, 0, NA, 4.5),
                     goff  = as.factor(c("haus", NA, "maus", NA, "maus")),
                     huft  = as.factor(c(NA, NA, "wolle", NA, "holz")),
                     mode  = c(5, NA, 2.5, NA, 4))

将其转换为时间序列对象会更好吗?

【问题讨论】:

    标签: r datatable time-series xts zoo


    【解决方案1】:

    这个问题是 OP 的问题 R combining duplicate rows in a time series with different column types in a datatable 的后续问题。

    OP 已请求通过聚合将不规则时间序列转换为规则时间序列。

    这可以通过右连接聚合和填充缺失值来实现。

    win <- 1   # step size of time series or length of time window
    brk <- dtRes[, .(time = tail(scales::fullseq(range(time), win), -1L))]
    dtRes[, lapply(.SD, function(x) if (is.numeric(x)) mean(x, na.rm = TRUE) 
                   else unlist(na.omit(unique(x)))), 
          by = .(time = ceiling(time / win) * win)][
            brk, on = .(time)]
    
       time abst farbe gier goff  huft mode
    1:    1    1 keine  2.5 haus  <NA>  4.0
    2:    1    1 keine  2.5 maus  <NA>  4.0
    3:    1    1 keine  2.5 toll  <NA>  4.0
    4:    2   NA  <NA>   NA <NA>  <NA>   NA
    5:    3    0 keine  0.0 maus wolle  2.5
    6:    4   NA  <NA>   NA <NA>  <NA>   NA
    7:    5    3   rot  3.0 maus  holz  3.0
    8:    5    3  blau  3.0 maus  holz  3.0
    

    为了创建常规时间序列,为了方便,使用来自 scales 包的 fullseq()。显然,OP 更喜欢右闭区间,因此可以跳过第一个值。

    警告信息

    `[.data.table`(dtRes, , lapply(.SD, function(x) if (is.numeric(x)) mean(x,:
    j 的第 1 组结果的第 5 项长度为零。这 将填充 3 个 NA 以匹配此结果中最长的列。 后面的组可能有类似的问题,但只报告第一个 保存填充警告缓冲区。

    可以愉快地忽略。

    发出警告是因为huft 对于time == 1NA。调用na.omit() 后,huft 列的结果向量为空,但组结果有 3 行。所以,data.tableNA 填充结果向量以获得匹配的长度——这是我们所期望的。


    该解决方案已参数化以适用于不同的块大小win。对于 win &lt;- 0.5 的块大小,例如,我们得到 ​​p>

        time abst farbe gier goff  huft mode
     1:  0.5    1 keine  2.5 haus  <NA>  4.0
     2:  1.0    1 keine  2.5 maus  <NA>  4.0
     3:  1.0    1 keine  2.5 toll  <NA>  4.0
     4:  1.5   NA  <NA>   NA <NA>  <NA>   NA
     5:  2.0   NA  <NA>   NA <NA>  <NA>   NA
     6:  2.5    0 keine  0.0 maus wolle  2.5
     7:  3.0   NA  <NA>   NA <NA>  <NA>   NA
     8:  3.5   NA  <NA>   NA <NA>  <NA>   NA
     9:  4.0   NA  <NA>   NA <NA>  <NA>   NA
    10:  4.5   NA  <NA>   NA <NA>  <NA>   NA
    11:  5.0    3   rot  3.0 maus  holz  3.0
    12:  5.0    3  blau  3.0 maus  holz  3.0
    

    还有很多行要填写。

    对于win &lt;- 2 的块大小,我们得到

       time abst farbe gier goff  huft mode
    1:    2    1 keine  2.5 haus  <NA>  4.0
    2:    2    1 keine  2.5 maus  <NA>  4.0
    3:    2    1 keine  2.5 toll  <NA>  4.0
    4:    4    0 keine  0.0 maus wolle  2.5
    5:    6    3   rot  3.0 maus  holz  3.0
    6:    6    3  blau  3.0 maus  holz  3.0
    

    每个时间间隔具有多行的时间序列不是常规时间序列,恕我直言。稍加修改,我们可以得到

    win <- 1
    brk <- dtRes[, .(time = scales::fullseq(range(time), win)[-1L])]
    dtRes[, lapply(.SD, function(x) if (is.numeric(x)) mean(x, na.rm = TRUE) 
                   else list(na.omit(unique(x)))), 
          by = .(time = ceiling(time / win) * win)][
            brk, on = .(time)]
    
       time abst    farbe gier           goff  huft mode
    1:    1    1    keine  2.5 haus,maus,toll        4.0
    2:    2   NA            NA                        NA
    3:    3    0    keine  0.0           maus wolle  2.5
    4:    4   NA            NA                        NA
    5:    5    3 rot,blau  3.0           maus  holz  3.0
    

    现在,每个时间步长只有一行,因为多个因子值已聚合到一个列表元素中。

    【讨论】:

    • 非常好的解决方案,非常感谢!如果我使用 1 的窗口,我总是会收到一条警告消息:警告消息:In '[.data.table'(dtRes, , lapply(.SD, function(x) if (is.numeric(x)) mean(x, : Item 5 of j's result for group 1 is zero length. This will be filled with 3 NAs to match the longest column in this result. Later groups may have a similar problem but only the first is reported to save filling the warning buffer. 我不知道这是否有问题,因为我不知道它的确切含义
    • @Bolle,我已经添加了警告信息的解释。
    【解决方案2】:

    这是data.table 答案:

    time 向上舍入到最接近的秒数:

    > dtRes[, 
    +       lapply(.SD, function(z) {return(ifelse(is.factor(z), levels(z)[unique(z)[1]], mean(z, na.rm = T)))} ), 
    +       by = .(time = round(time, digits = 0))]
       time abst farbe gier goff  huft mode
    1:    0    1 keine  2.5 haus  <NA>  4.0
    2:    1    1 keine  2.5 maus  <NA>  4.0
    3:    2    0 keine  0.0 maus wolle  2.5
    4:    5    3   rot  3.0 maus  holz  3.0
    

    使用ceiling函数:

    > dtRes[, 
    +       lapply(.SD, function(z) {return(ifelse(is.factor(z), levels(z)[unique(z)[1]], mean(z, na.rm = T)))} ), 
    +       by = .(time = ceiling(time))]
       time abst farbe gier goff  huft mode
    1:    1    1 keine  2.5 haus  <NA>  4.0
    2:    3    0 keine  0.0 maus wolle  2.5
    3:    5    3   rot  3.0 maus  holz  3.0
    

    您可以根据需要调整返回level 的逻辑。在这里,我返回与第一个非唯一值对应的 level

    您可以切换到在ifelse 语句中使用as.numeric - 结果相似。我意识到factor 列的数据类型更改为character - 如果您需要factor,那么您可以在单独的语句中专门设置它或使用链接。

    dtRes[, lapply(.SD, ....), by = .(....)][, lapply(.SD, as.factor(...)), .SDcols = .( columns you want as factors), ]
    

    【讨论】:

      【解决方案3】:

      不完全确定你想做什么,但如果我理解正确的话是这样的:

      dtRes %>% 
        group_by(second = ceiling(time)) %>% 
        summarise(abst = mean(abst),
                  farbe = farbe[1],
                  gier = mean(gier),
                  goff = goff[1],
                  huft = huft[1],
                  mode = mean(mode)) %>% 
        add_row(second = c(1:10)[!(c(1:10) %in% .$second)]) %>% #change 10 to however many seconds you will have
        arrange(second)
      
      # A tibble: 10 x 7
         second  abst farbe  gier goff  huft   mode
          <dbl> <dbl> <fct> <dbl> <fct> <fct> <dbl>
       1      1     1 keine   2.5 haus  NA        4
       2      2    NA NA     NA   NA    NA       NA
       3      3     0 keine   0   maus  wolle    NA
       4      4    NA NA     NA   NA    NA       NA
       5      5     3 rot     3   maus  holz      3
       6      6    NA NA     NA   NA    NA       NA
       7      7    NA NA     NA   NA    NA       NA
       8      8    NA NA     NA   NA    NA       NA
       9      9    NA NA     NA   NA    NA       NA
      10     10    NA NA     NA   NA    NA       NA
      

      请注意,从您的示例中不清楚您如何将时间四舍五入到秒,但我认为您总是想四舍五入?

      【讨论】:

        猜你喜欢
        • 2011-04-23
        • 2014-09-02
        • 1970-01-01
        • 2019-08-31
        • 2011-11-17
        • 1970-01-01
        • 2017-03-06
        • 2016-04-07
        • 1970-01-01
        相关资源
        最近更新 更多