отмечать группы с одинаковыми строками в некоторых столбцах таблицы data.table - PullRequest
2 голосов
/ 19 июня 2020

У меня есть большая таблица данных, структура которой аналогична этому воспроизводимому примеру:

d <- data.table(
  g     =c(1  ,1  ,2  ,2  ,2  ,3  ,3  , 4 , 4),
  A     =c('a','a','b','b','w','c','q','r','r'),
  B     =c(1  ,1  ,2  ,2  ,2  ,3  ,3  ,4  , 5),
  sameA =c(T  , T , F , F , F , F , F , T , T),
  sameAB=c(T  , T , F , F , F , F , F , F , F)
 )

g обозначает группу, а A и B - индивидуальные характеристики. Я хочу создать переменные:

  • sameA: указывает, что A одинаково для всех наблюдений группы
  • sameAB: указывает, что A и B одинаковы для всех наблюдений группы

как я могу сделать это эффективно с помощью data.table?

Ответы [ 3 ]

3 голосов
/ 19 июня 2020

Возможно, вы могли бы попробовать это. Используйте uniqueN, чтобы определить количество уникальных значений в группе (с by = g), и сравните с 1.

library(data.table)

d[, c("sameAnew", "saveABnew") := list(uniqueN(A) == 1, uniqueN(A) == 1 & uniqueN(B) == 1), by = g]

Или, как предлагает @jangorecki, создайте временную переменную, которая подавляется фигурными скобками { }, чтобы избежать повторения uniqueN(A):

d[, c("sameAnew", "saveABnew") := {tmp <- uniqueN(A); list(tmp == 1, tmp == 1 & uniqueN(B) == 1)}, by = g]

Output

   g A B sameA sameAB sameAnew saveABnew
1: 1 a 1  TRUE   TRUE     TRUE      TRUE
2: 1 a 1  TRUE   TRUE     TRUE      TRUE
3: 2 b 2 FALSE  FALSE    FALSE     FALSE
4: 2 b 2 FALSE  FALSE    FALSE     FALSE
5: 2 w 2 FALSE  FALSE    FALSE     FALSE
6: 3 c 3 FALSE  FALSE    FALSE     FALSE
7: 3 q 3 FALSE  FALSE    FALSE     FALSE
8: 4 r 4  TRUE  FALSE     TRUE     FALSE
9: 4 r 5  TRUE  FALSE     TRUE     FALSE
1 голос
/ 20 июня 2020

Вот еще один вариант:

isdup <- function(x) duplicated(x) | duplicated(x, fromLast=TRUE)

d[, adup := isdup(.SD), .SDcols=c("g", "A")][,
    sameA2 := !any(!adup), g]

d[, sameAB2 := FALSE][
    (sameA2), bdup := isdup(.SD), .SDcols=c("g", "B")][
        (sameA2), sameAB2 := !any(!bdup), g]

И неортодоксальная версия by:

d[order(g, A, B), c("sameA3", "sameAB3") := {
    a <- rleid(g, A)
    b <- rleid(g, B)
    newg <- which(diff(g) > 0L)

    nas <- rep(NA_integer_, .N)
    acnt <- a - nafill(nafill(replace(nas, newg + 1L, a[newg]), "locf"), fill=0L)
    bcnt <- b - nafill(nafill(replace(nas, newg + 1L, b[newg]), "locf"), fill=0L)

    acnt[-c(newg, .N)] <- NA_integer_
    acnt <- nafill(acnt, "nocb")
    bcnt[-c(newg, .N)] <- NA_integer_
    bcnt <- nafill(bcnt, "nocb")

    l <- acnt == 1L
    .(l, l & bcnt == 1L)
}]

Не могли бы вы поделиться таймингами для вашего большого набора данных?

1 голос
/ 19 июня 2020

Ваше объяснение того, что вы ожидаете, не совсем точно, чтобы я мог знать, собираюсь ли я дать вам ответ, который вы ищете.

Моя интерпретация такова. , «Мне нужна таблица данных только с уникальными строками»

В этом случае должно работать следующее:

d <- as.data.frame(d)
d <- data.table::data.table(unique.data.frame(d))
...