5

各行に時間イベントを持つデータ フレームがあります。1 つの行には送信者のイベント タイプ (typeid=1) があり、もう 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) を持つデータ フレームの場合は、多くの時間がかかります。

for ループをより最適化された R 関数に置き換えるにはどうすればよいですか? lapply を使用してそのような計算を行うことはできますか? もしそうなら、例を挙げていただけますか?

前もって感謝します、

4

4 に答える 4

4

通常の解決策は、ベクトル化されたものを見つけるために問題を十分に検討することです。

それが失敗した場合は、C++ でループを書き直すことに頼ることがあります。Rcppパッケージはインターフェースに役立ちます。

于 2010-09-10T12:01:23.943 に答える
2

Dirk が言ったように: ベクトル化が役に立ちます。この例は、呼び出しをas.numericループの外に移動することです (この関数はベクトルで動作するため)。

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

他に役立つ可能性のあるものは次のとおりです。

新しい変数を作成せずaRec <- dDelay[itr,]に の行にアクセスできるので、行を気にする必要はありません。dDelay

myDelayループ内で成長させるとボトルネックになる可能性があるため、事前に割り当てます。詳細については、ジョシュアの回答を参照してください。

于 2010-09-10T14:06:49.667 に答える
2

関数の*applyスイートは、ループ用に最適化されていません。さらに、より多くのメモリを使用し、マシンがスワップするapplyため、 for ループの方が高速であるという問題に取り組みました。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 に答える