【问题标题】:Vectorizing for loop: access previous rows of data.frame矢量化 for 循环:访问 data.frame 的前几行
【发布时间】:2016-05-09 22:58:00
【问题描述】:

我正在尝试将循环转换为矢量化。在我的应用程序中,我有超过 200 万行并且循环太慢了。我读过这篇很有帮助的帖子:Speed up the loop operation in R

这是我的数据的示例:

m <- data.frame(time = 1:10, level = c(0,0,60,100,0,0,100,100,0,0))

>m
    time level
1     1     0
2     2     0
3     3    60
4     4   100
5     5     0
6     6     0
7     7   100
8     8   100
9     9     0
10   10     0

我想要的是一个列machine,根据级别“开”或“关”。

如果 level != 0 那么 machine = "on"

如果级别变为 0,则在任意时间段 lag 之后,machine 将关闭。在这个例子中,说lag = 2,那么结果将是:

    time level machine
1     1     0     off
2     2     0     off
3     3    60      on
4     4   100      on
5     5     0      on
6     6     0     off
7     7   100      on
8     8   100      on
9     9     0      on
10    10    0     off

关于如何向量化这个操作有什么建议吗?我已经研究过使用来自 dplyr 的lag,但还没有找到让它工作的方法。

我已经编写了一个适用于此示例的循环,作为说明。

m$machine <- ifelse(m$level!=0, "on", 0)

tlag <- 2
# check to see if timeout period has elapsed
for (i in seq_along(m$machine)){
    if(m$machine[i]!="on") {
        nback <- i - tout
        if (nback <=0 ) nback <- 1
        if (sum(m$level[nback:i]) == 0){ #light should be off
            m$machine[i] <- "off"
        }
    }
}

for (i in seq_along(m$machine)){
    if(m$machine[i]==0) m$machine[i] <- "on"   
}

【问题讨论】:

    标签: r


    【解决方案1】:

    这是使用dplyr 包的lag 运算符的一种解决方案:

    library(dplyr)
    m %>% mutate(machine = ifelse((level != 0 |
                                   (level == 0 &
                                    lag(level, 1, default = 0) != 0)),
                                  'on', 'off'))
    

    输出如下:

       time level machine
    1     1     0     off
    2     2     0     off
    3     3    60      on
    4     4   100      on
    5     5     0      on
    6     6     0     off
    7     7   100      on
    8     8   100      on
    9     9     0      on
    10   10     0     off
    

    【讨论】:

      【解决方案2】:

      你可以用 data.table 做到这一点:

      library(data.table)
      m <- data.table(time = 1:10, level = c(0,0,60,100,0,0,100,100,0,0))
      m[, machine := {lag.level = shift(level, 1, fill = 0); 
                      ifelse(level != 0 | lag.level != 0, "on", "off") },]
      

      【讨论】:

        猜你喜欢
        • 2014-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-03
        • 2017-02-01
        • 2018-10-15
        • 2019-12-02
        相关资源
        最近更新 更多