5

我有一个数据框,每行都有时间事件。在一行中,我有发送者的事件类型(typeid = 1),而在另一行中,我有接收者的事件类型(typeid = 2)。我想计算发送者和接收者之间的延迟(时间差)。

我的数据组织在一个 data.frame 中,如下图所示:

dd[1:10,]
     timeid   valid typeid
1  18,00035 1,00000      1
2  18,00528 0,00493      2
3  18,02035 2,00000      1
4  18,02116 0,00081      2
5  18,04035 3,00000      1
6  18,04116 0,00081      2
7  18,06035 4,00000      1
8  18,06116 0,00081      2
9  18,08035 5,00000      1
10 18,08116 0,00081      2

calc_DelayVIDEO <- function (dDelay ){

        pktProcess <- TRUE
        nLost <- 0
        myDelay <- data.frame(time=-1, delay=-1, jitter=-1, nLost=-1)
        myDelay <- myDelay[-1, ]
        tini <- 0
        tend <- 0
        for (itr in c(1:length(dDelay$timeid))) {
           aRec <- dDelay[itr,]
           if (aRec$typeid == 1){
                tini <- as.numeric(aRec$timeid)
                if (!pktProcess ) {
                   nLost <- (nLost + 1)
                   myprt(paste("Packet Lost at time ", aRec$timeid, " lost= ", nLost, sep=""))
                }

                pktProcess <- FALSE 
           }else if (aRec$typeid == 2){

                tend <- as.numeric(aRec$timeid)
                dd <- tend - tini
                jit <- calc_Jitter(dant=myDelay[length(myDelay), 2], dcur=dd)
                myDelay <- rbind(myDelay, c(aRec$timeid, dd, jit, nLost))
                pktProcess <- TRUE
                #myprt(paste("time=", aRec$timeev, " delay=", dd, " Delay Var=", jit, " nLost=", nLost ))
           }
        }
        colnames(myDelay) <- c("time", "delay", "jitter", "nLost")
        return (myDelay)
}

为了计算延迟,我使用 calc_DelayVideo 函数,但对于具有大量记录(~60000)的数据帧,它需要很多时间。

如何用更优化的 R 函数替换 for 循环?我可以使用 lapply 来做这样的计算吗?如果是这样,你能给我举个例子吗?

提前致谢,

4

4 回答 4

4

通常的解决方案是对问题进行足够认真的思考以找到矢量化的东西。

如果失败了,我有时会求助于用 C++ 重写循环;Rcpp可以帮助界面。

于 2010-09-10T12:01:23.943 回答
2

正如 Dirk 所说:矢量化会有所帮助。这方面的一个例子是将调用as.numeric移出循环(因为此函数适用于向量)。

dDelay$timeid <- as.numeric(dDelay$timeid)

其他可能有帮助的事情是

不用担心 line aRec <- dDelay[itr,],因为您可以只访问 的行dDelay,而无需创建新变量。

预分配myDelay,因为让它在循环中增长很可能是一个瓶颈。有关更多信息,请参阅 Joshua 的回答。

于 2010-09-10T14:06:49.667 回答
2

这套*apply函数没有针对循环进行优化。此外,我还解决了 for 循环比使用更多内存并导致我的机器交换apply更快的问题。apply

我建议完全初始化myDelay对象并避免使用rbind(必须重新分配内存):

init <- rep(NA, length(dDelay$timeid))
myDelay <- data.frame(time=init, delay=init, jitter=init, nLost=init)

然后替换:

myDelay <- rbind(myDelay, c(aRec$timeid, dd, jit, nLost))

myDelay[i,] <- c(aRec$timeid, dd, jit, nLost)
于 2010-09-10T12:17:38.573 回答
0

另一个优化:如果我正确阅读了您的代码,您可以使用以下方法轻松计算向量 nLost:

nLost <-cumsum(dDelay$typeid==1)

在循环之外。最后,您可以将其添加到数据框中。已经为您节省了大量时间。如果我使用你的数据框,那么:

> nLost <-cumsum(dd$typeid==1)
> nLost
 [1] 1 1 2 2 3 3 4 4 5 5

同样,包裹丢失的时间可以计算为:

> dd$timeid[which(dd$typeid==1)]
[1] 18,00035 18,02035 18,04035 18,06035 18,08035

以防您也想在某个地方报告它们。

为了测试,我使用了:

dd <- structure(list(timeid = structure(1:10, .Label = c("18,00035", 
"18,00528", "18,02035", "18,02116", "18,04035", "18,04116", "18,06035", 
"18,06116", "18,08035", "18,08116"), class = "factor"), valid = structure(c(3L, 
2L, 4L, 1L, 5L, 1L, 6L, 1L, 7L, 1L), .Label = c("0,00081", "0,00493", 
"1,00000", "2,00000", "3,00000", "4,00000", "5,00000"), class = "factor"), 
    typeid = c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L)), .Names = c("timeid", 
"valid", "typeid"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10"))
于 2010-09-10T14:35:50.983 回答