Вот одно потенциальное, хотя и несколько не элегантное, решение
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;если во фрейме данных более 1 строки, вернуть NULL, если нет, вернуть фрейм данных 1 строки.
- Строка 3: перебрать выходные данные из Строки 2;возвращать только ненулевые компоненты
- Строка 4: нужно связать, построчно, вывод из строки 3, который мы организуем через
do.call()
Это может быть упрощено до двух строк, объединяя строки 1-3 в одну строку:
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))