所以这个问题一直困扰着我,因为我一直在寻找一种有效的方法。基本上,我有一个数据框,每行都有一个实验数据样本。我想这应该被视为实验中的日志文件,而不是分析数据的最终版本。
我遇到的问题是,某些事件会不时记录在数据列中。为了使分析易于处理,我想要做的是为事件之间的空单元格“填补空白”,以便数据中的每一行都可以绑定到最近发生的事件。这有点难以解释,但这是一个例子:
现在,我想把它变成这个:
这样做可以让我按当前事件分割数据。在任何其他语言中,我会跳转到使用for循环来执行此操作,但我知道R对于那种类型的循环并不是很好,并且在这种情况下,我有数十万行数据要进行排序,所以我想知道是否有人可以提供快速的方式来做这个建议吗?
非常感谢。
答案 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
解释代码,
na.locf(log_message)
返回一个因素(就是在dat
中创建数据的方式),NA
s替换为之前的非NA
值(最后一个)结转部分)。strplit()
在此字符向量上运行,在下划线上将其分开。 strsplit()
返回一个列表,其中包含与字符向量中的元素一样多的元素。在这种情况下,每个组件是长度为2的向量。我们想要这些向量的第一个元素,sapply()
运行子集化函数'['()
并从每个列表组件中提取第一个元素。transform()
中,所以i)我不需要引用dat$
,因此我可以将结果作为新变量直接添加到数据dat
中