2017-05-08 3 views
0

私はすぐに説明する方法を知らない。私は自分のベストを尽くす:インデックスデータを使用して許容値でデータをグループ化する

Data<-data.frame(A=c(1,2,3,5,8,9,10),B=c(5.3,9.2,5,8,10,9.5,4),C=c(1:7))

Indの値がDataC列に対応するインデックス

Ind<-data.frame(I=c(5,6,2,4,1,3,7))

: は、私は、次の例のデータを持っています。今度は、最初のIndの値から始め、Data data.frame(対応する列はC)にあります。その行から上下に移動して、許容範囲1の値を列Aで検索します。これらの値を結果データフレームに書き込んで、グループID列を追加し、データフレーム内で削除したいData(ここで、Iそれらを見つけた)。次に、インデックスデータフレームIndの次のエントリから開始し、data.frame Dataが空になるまで開始します。私が書くと、削除する私のDataとどのように列Cとループの中に他のものと私のIndと一致する方法を知っているが、私はここで私の質問です主なポイント、知らない:

私が発見しましたDataの私の行、どのように私のGroup IDを得るために、そのエントリの上下の許容範囲内の列Aのフィッティング値を調べることができますか?私が取得したいもの

は、この結果である:

A  B  C  Group 
1  5.3 1  2    
2  9.2 2  2     
3  5  3  2    
5  8  4  3   
8  10 5  1     
9  9.5 6  1     
10 4  7  4 

たぶん誰かが高速な方法でこの問題を解決する方法としても私の質問では臨界点で私を助けたりできます。

多くの感謝!

答えて

1

一般的には、ループ内で行単位でデータフレームを削除または拡大しないでください。 Rのメモリ管理は、行を追加または削除するたびに、データフレームの別のコピーが作成されることを意味します。ガベージコレクションは最終的にデータフレームの「古い」コピーを破棄しますが、ゴミはすぐに蓄積され、パフォーマンスが低下します。代わりに、Dataデータフレームに論理列を追加し、抽出された行をTRUEに設定します。そうですね。

Data$extracted <- rep(FALSE,nrow(Data)) 

あなたの問題について:私は異なるグループ番号を取得しますが、グループは同じです。

これを行うにはよりエレガントな方法があるかもしれませんが、これで完了します。

# store results in a separate list 
res <- list() 

group.counter <- 1 

# loop until they're all done. 
for(idx in Ind$I) { 
    # skip this iteration if idx is NA. 
    if(is.na(idx)) { 
    next 
    } 

    # dat.rows is a logical vector which shows the rows where 
    # "A" meets the tolerance requirement. 
    # specify the tolerance here. 
    mytol <- 1 
    # the next only works for integer compare. 
    # also not covered: what if multiple values of C 
    # match idx? do we loop over each corresponding value of A, 
    # i.e. loop over each value of 'target'? 
    target <- Data$A[Data$C == idx] 

    # use the magic of vectorized logical compare. 
    dat.rows <- 
    ((Data$A - target) >= -mytol) & 
    ((Data$A - target) <= mytol) & 
    (! Data$extracted) 
    # if dat.rows is all false, then nothing met the criteria. 
    # skip the rest of the loop 
    if(! any(dat.rows)) { 
    next 
    } 

    # copy the rows to the result list. 
    res[[length(res) + 1]] <- data.frame(
    A=Data[dat.rows,"A"], 
    B=Data[dat.rows,"B"], 
    C=Data[dat.rows,"C"], 
    Group=group.counter # this value will be recycled to match length of A, B, C. 
) 

    # flag the extraction. 
    Data$extracted[dat.rows] <- TRUE 
    # increment the group counter 
    group.counter <- group.counter + 1 
} 

# now make a data.frame from the results. 
# this is the last step in how we avoid 
#"growing" a data.frame inside a loop. 
resData <- do.call(rbind, res) 
+0

ありがとうございました! – JmO

+0

これは「最適な」グループ分けを与えないことに注意してください。クラスタ分析用のパッケージがあります。しかし、これがあなたのニーズを満たしていれば、十分です。 – Jason

+0

もう一度、ありがとう、あなたはここでパッケージをお勧めしますか? – JmO

関連する問題