Я работал над проблемой, где у меня было две переменные группировки и одно значение. Я только для того, чтобы в строках было не менее двух значений в группе, близких по значению друг к другу. В примере я хотел, чтобы группы имели один набор значений в пределах 10 друг от друга.

Ниже я сначала попробовал, и кое-что о создании переменной флага заставило меня почувствовать, что я делал это каким-то окольным путем, и я просто хотел узнать, есть ли более понятный, более намеченный способ сделать что-то подобное в data.table. Спасибо!

X и y - категории, z - значение.

library(data.table)
set.seed(123)


dt <- data.table(
  x = sample(LETTERS, 1000, T),
  y = sample(letters, 1000, T),
  z = sample(100, 1000, T),
  key = tail(letters, 3)
)

dt <- unique(dt)
dt <- dt[dt[, .(flag = any(diff(z) <= 11)), .(x, y)], on = c("x", "y")][(flag)]
dt[, flag := NULL]
dt
2
James B 15 Авг 2019 в 18:48

2 ответа

Лучший ответ

Ты мог бы сделать

res <- dt[, if (.N > 1L && min(diff(z)) <= 11) .SD, by=.(x, y)]

Я использовал min вместо any, так как, я думаю, это приводит к меньшему количеству вычислений.

Я добавил условие .N > 1L, так как вам нужно подумать о том, как обрабатывать однострочный случай (где diff - это NA). Вы могли бы сделать

  • .N > 1L && отбросить эти дела
  • .N == 1L || чтобы оставить их

Я просто хотел узнать, есть ли более понятный способ сделать что-то подобное в data.table

Я думаю, having= синтаксис был бы удобен для этого. В настоящее время это запрос функции.


Входные данные (так как OP перезаписывает их):

library(data.table)
set.seed(123)
dt <- data.table(
  x = sample(LETTERS, 1000, T),
  y = sample(letters, 1000, T),
  z = sample(100, 1000, T),
  key = tail(letters, 3)
)
dt <- unique(dt)
3
Frank 15 Авг 2019 в 19:25

Вы можете использовать .I с if, чтобы определить, включать ли каждую группу (здесь want соответствует вашему окончательному dt)

dt <- unique(dt)
want <- dt[dt[, if(any(diff(z) <= 11)) .I, .(x, y)]$V1]
4
IceCreamToucan 15 Авг 2019 в 16:05