これが、ややエレガントではないにしても、1つの潜在的な解決策です。
out <- with(dat, split(dat, interaction(column2, column3)))
out <- lapply(out, function(x) if(NROW(x) > 1) {NULL} else {data.frame(x)})
out <- out[!sapply(out, is.null)]
do.call(rbind, out)
これは次のようになります。
> do.call(rbind, out)
row.no column2 column3 column4
bb.yy 4 bb yy down
bb.zz 5 bb zz up
いくつかの説明、行ごと:
- 1行目:データをリストに分割します。各コンポーネントは、との一意の組み合わせによって形成されたグループに対応する行を持つデータフレーム
column2
ですcolumn3
。
- 2行目: 1行目の結果を繰り返し処理します。データフレームに複数の行がある場合はNULLを返し、そうでない場合は1行のデータフレームを返します。
- 3行目: 2行目からの出力を繰り返します。NULL以外のコンポーネントのみを返します
- 4行目: 3行目からの出力を行ごとにバインドする必要があります。
do.call()
これは、1〜3行目を1行にまとめて、2行に簡略化できます。
out <- lapply(with(dat, split(dat, interaction(column2, column3))),
function(x) if(NROW(x) > 1) {NULL} else {data.frame(x)})
do.call(rbind, out[!sapply(out, is.null)])
上記はすべて次のように行われました。
dat <- structure(list(row.no = 1:5, column2 = structure(c(1L, 1L, 1L,
1L, 1L), .Label = "bb", class = "factor"), column3 = structure(c(1L,
1L, 1L, 2L, 3L), .Label = c("ee", "yy", "zz"), class = "factor"),
column4 = structure(c(2L, 1L, 2L, 1L, 2L), .Label = c("down",
"up"), class = "factor")), .Names = c("row.no", "column2",
"column3", "column4"), class = "data.frame", row.names = c(NA,
-5L))