2

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

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

来自基础数据集的 RStudio 的数据帧屏幕截图

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

在此处输入图像描述

这样做将使我能够按当前事件拆分数据。在任何其他语言中,我都会使用 for 循环来执行此操作,但我知道 R 不适合这种类型的循环,而且在这种情况下,我有数十万行数据要排序,所以想知道是否有人可以提供建议以快速完成此操作?

非常感谢。

4

2 回答 2

5

这个问题已经在这个网站上以各种形式被问过很多次了。标准答案是使用zoo::na.locf. 搜索 [r]na.locf以查找如何使用它的示例。

这是在基础 R 中使用的另一种方法rle

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
于 2013-01-31T20:41:56.573 回答
3

na.locf()zoo中的功能在这里很有用,例如

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),其中NAs 替换为前一个非NA值(最后一个结转部分)。
  2. 然后将 1. 的结果转换为字符串
  3. strplit()在此字符向量上运行,并在下划线处将其分开。strsplit()返回一个包含与字符向量中的元素一样多的元素的列表。在这种情况下,每个分量都是长度为 2 的向量。我们想要这些向量的第一个元素,
  4. 所以我使用sapply()运行子集函数'['()并从每个列表组件中提取第一个元素。
  5. 整个事情都包含在其中,transform()所以 i) 我不需要参考dat$,因此我可以将结果作为新变量直接添加到数据dat中。
于 2013-01-31T20:45:09.660 回答