【发布时间】:2020-03-12 12:59:08
【问题描述】:
我有一个问题,我可以用 R 中缓慢而笨拙的循环来解决。但是,我希望有一个更优雅(和更快)的解决方案......
我能想到的最简单的解释:每一行数据描述一个开关上的动作。这些行按开关 ID(开关 1、开关 2 等)和操作的时间顺序排序。每个开关可以在任何时间点打开或关闭。动作可以是“打开”、“关闭”或“离开”。对于每一行,我想知道该行描述的操作之前和之后的开关状态(打开或关闭)。
每个开关都从“关闭”位置开始。
(我正在使用的数据实际上与保险单数据相关,但这种基于开关的类比有效,并且可能更易于理解)
一个可重现的例子:
df <- data.frame(switch_id = c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3),
counter = c(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4),
action = c("on", "off", "on", "off", "on", "same", "same", "same", "on", "same", "same", "same", "off", "off", "off", "on", "off", "same", "on"))
我可以使用不特别优雅的循环到达我想要的位置:
df$status_before <- NA
df$status_after <- NA
for(i in 1:nrow(df))
{
if(df$counter[i] == 1)
{
df$status_before[i] <- FALSE # switch always starts in the "off" position
}
else
{
df$status_before[i] <- df$status_after[i-1]
}
if(df$action[i] == "on") {
df$status_after[i] <- TRUE
}
else if(df$action[i] == "off")
{
df$status_after[i] <- FALSE
}
else # "same"
{
df$status_after[i] <- df$status_before[i] # leave everything alone
}
}
...但显然在 R 中最好避免循环,因为它们运行非常缓慢。当然,在这个小数据集中没关系,但我正在处理的真实数据有大约 100 万行,所以这可能是个问题。
是否有“矢量化”解决方案,可能使用dplyr 类型命令?
谢谢。
【问题讨论】: