3

次のようなデータフレームがあります。

df <- data.frame(
  Logical = c(TRUE,FALSE,FALSE,FALSE,FALSE,FALSE),
  A = c(1,2,3,2,3,1),
  B = c(1,0.05,0.80,0.05,0.80,1),
  C = c(1,10.80,15,10.80,15,1))

次のようになります。

  Logical A    B    C
1    TRUE 1 1.00  1.0
2   FALSE 2 0.05 10.8
3   FALSE 3 0.80 15.0
4   FALSE 2 0.05 10.8
5   FALSE 3 0.80 15.0
6   FALSE 1 1.00  1.0

D次のルールに基づく整数である新しい変数 を追加したい: a 0if df$Logicalis TRUE、または変数のすべての行で同じ整数であり、AおよそB(Cそれらは double であるため、浮動小数点誤差のマージン) と等しく、 から始まり1ます。

ここで期待される出力:

  Logical A    B    C D
1    TRUE 1 1.00  1.0 0
2   FALSE 2 0.05 10.8 1
3   FALSE 3 0.80 15.0 2
4   FALSE 2 0.05 10.8 1
5   FALSE 3 0.80 15.0 2
6   FALSE 1 1.00  1.0 3

最初の行はで0あるために取得し、2 番目と 4 番目の行は変数であるために取得し、2 番目と 5 番目の行でもほぼ同じです。行 6は、次の一意の行であるため、 を取得します。に割り当てられた整数の順序は、を除いて無関係であることに注意してください。たとえば、行 2 と 4 は、この整数が の他のケースで一意である限り、割り当てることもできます。LogicalTRUE1ABC3D02D


集計関数の使用を検討しました。たとえば、次を使用しddplyます。

library("plyr")
df$foo <- 1:nrow(df)
foo <- dlply(df,.(A,B,C),'[[',"foo")
df$D <- 0
for (i in 1:length(foo)) df$D[foo[[i]]] <- i
df$D[df$Logical] <- 0

動作しますが、これが浮動小数点エラーでどの程度うまくいくかはわかりません (この呼び出しの前にここで値を丸めることができ、かなり安定しているはずです)。ループを使用すると、非常に簡単です。

df$D <- 0
c <- 1
for (i in 1:nrow(df))
{
  if (!isTRUE(df$Logical[i]) & df$D[i]==0)
  {
    par <- sapply(1:nrow(df),function(j)!df$Logical[j]&isTRUE(all.equal(unlist(df[j,c("A" ,"B", "C")]),unlist(df[i,c("A" ,"B", "C")]))))
    df$D[par] <- c
    c <- c+1
  }
}

しかし、これは大きなデータ フレームでは非常に遅くなります。

4

1 に答える 1

4

以下の Matthew Dowle のコメントによると、data.table数値をグループ化し、それらを.Machine$double.eps^.5許容範囲で区別できます。それを念頭に置いて、data.table解決策はうまくいくはずです:

library(data.table)

DT <- as.data.table(df)

DT[, D := 0]

.GRP <- 0

DT[!Logical, D := .GRP <- .GRP + 1, by = "A,B,C"]

#    Logical A    B    C foo D
# 1:    TRUE 1 1.00  1.0   1 0
# 2:   FALSE 2 0.05 10.8   2 1
# 3:   FALSE 3 0.80 15.0   3 2
# 4:   FALSE 2 0.05 10.8   4 1
# 5:   FALSE 3 0.80 15.0   5 2
# 6:   FALSE 1 1.00  1.0   6 3

Matthew Dowle がここに書いている.GRPように、data.table 1.8.3 で実装されていますが、私はまだ 1.8.2 を使用しています。


コメントのフォローアップです。1.8.2 の NEWS アイテムです。に追加し?data.tableます。強調表示していただきありがとうございます。

数値列 (タイプdouble) がキーおよびアドホック バイで許可されるようになりました。 J()を強要しSJ()なくなりました。数値型が一致しない結合列は、暗黙のうちにの結合列の型と一致するように強制されます。デフォルトでは、2 つの浮動小数点値の差が sqrt(.Machine$double.eps) 以内の場合、(グループ化と二分探索の結合によって) 等しいと見なされます。の例を参照してください。FR #951、#1609、および #1075 を完了します。これにより、 ( や など)を使用する他のアトミック型への道が開かれます。ベータ テストと 2 つの数値列のキーに関する問題の発見 (バグ #2004) を行った Chris Neff に感謝し、修正し、テストを追加しました。doubleintegerix?unique.data.tabledoublePOSIXctbit64

于 2012-10-25T12:26:18.803 に答える