填补R中时间序列数据的差距

时间:2013-01-31 20:23:11

标签: r time-series

所以这个问题一直困扰着我,因为我一直在寻找一种有效的方法。基本上,我有一个数据框,每行都有一个实验数据样本。我想这应该被视为实验中的日志文件,而不是分析数据的最终版本。

我遇到的问题是,某些事件会不时记录在数据列中。为了使分析易于处理,我想要做的是为事件之间的空单元格“填补空白”,以便数据中的每一行都可以绑定到最近发生的事件。这有点难以解释,但这是一个例子:

Screenshot of dataframe from RStudio of base dataset

现在,我想把它变成这个:

enter image description here

这样做可以让我按当前事件分割数据。在任何其他语言中,我会跳转到使用for循环来执行此操作,但我知道R对于那种类型的循环并不是很好,并且在这种情况下,我有数十万行数据要进行排序,所以我想知道是否有人可以提供快速的方式来做这个建议吗?

非常感谢。

2 个答案:

答案 0 :(得分:5)

此问题已多次在本网站上以各种形式提出。标准答案是使用zoo::na.locf。在[r]中搜索na.locf以查找如何使用它的示例。

以下是使用rle的基础R的替代方法:

d <- data.frame(LOG_MESSAGE=c('FIRST_EVENT', '', 'SECOND_EVENT', '', ''))
within(d, {
    # ensure character data
    LOG_MESSAGE <- as.character(LOG_MESSAGE)
    CURRENT_EVENT <- with(rle(LOG_MESSAGE), # list with 'values' and 'lengths'
                          rep(replace(values, 
                                      nchar(values)==0, 
                                      values[nchar(values) != 0]), 
                              lengths))
})
#    LOG_MESSAGE CURRENT_EVENT
# 1  FIRST_EVENT   FIRST_EVENT
# 2                FIRST_EVENT
# 3 SECOND_EVENT  SECOND_EVENT
# 4               SECOND_EVENT
# 5               SECOND_EVENT

答案 1 :(得分:3)

zoo 包中的na.locf()函数在这里很有用,例如

require(zoo)
dat <- data.frame(ID = 1:5, sample_value = c(34,56,78,98,234),
                  log_message = c("FIRST_EVENT", NA, "SECOND_EVENT", NA, NA))

dat <-
  transform(dat,
            Current_Event = sapply(strsplit(as.character(na.locf(log_message)), 
                                            "_"),
                                   `[`, 1))

给出

> dat
  ID sample_value  log_message Current_Event
1  1           34  FIRST_EVENT         FIRST
2  2           56         <NA>         FIRST
3  3           78 SECOND_EVENT        SECOND
4  4           98         <NA>        SECOND
5  5          234         <NA>        SECOND

解释代码,

  1. na.locf(log_message)返回一个因素(就是在dat中创建数据的方式),NA s替换为之前的非NA值(最后一个)结转部分)。
  2. 然后将1.的结果转换为字符串
  3. strplit()在此字符向量上运行,在下划线上将其分开。 strsplit()返回一个列表,其中包含与字符向量中的元素一样多的元素。在这种情况下,每个组件是长度为2的向量。我们想要这些向量的第一个元素,
  4. 所以我使用sapply()运行子集化函数'['()并从每个列表组件中提取第一个元素。
  5. 整件事情都包含在transform()中,所以i)我不需要引用dat$,因此我可以将结果作为新变量直接添加到数据dat