Портирование операций над множествами из фреймов данных R в таблицы данных: как определить дублированные строки?

[Обновление 1: как заметил Мэтью Доул, я использую data.table Версия 1.6.7 на R-Forge, а не на CRAN. Вы не увидите такого же поведения с более ранней версией data.table.]

В качестве фона: я портирую некоторые маленькие служебные функции для выполнения операций над множествами строк данных или пар кадров данных (т. Е. Каждая строка является элементом в наборе), например, уникальная - для создания набора из списка, объединения, пересечение, разность множеств и т. д. Эти имитаторы Matlab's intersect(...,'rows'), setdiff(...,'rows')и т. д., которые, по-видимому, не имеют аналогов в R (операции множеств R ограничены векторами и списками, но не строками матриц или фреймами данных). Примеры этих маленьких функций приведены ниже. Если эта функциональность для фреймов данных уже существует в некотором пакете или базе R, я открыт для предложений.

Я перенес их в таблицы данных, и одним из необходимых шагов в текущем подходе является поиск дублированных строк. когда duplicated() выполняется ошибка, возвращающая, что таблицы данных должны иметь ключи. Это досадный блокпост - кроме установки ключей, который не является универсальным решением и увеличивает вычислительные затраты, есть ли другой способ найти дублированные объекты?

Вот воспроизводимый пример:

library(data.table)
set.seed(0)
x   <- as.data.table(matrix(sample(2, 100, replace = TRUE), ncol = 4))
y   <- as.data.table(matrix(sample(2, 100, replace = TRUE), ncol = 4))

res3    <- dt_intersect(x,y)

Получив это сообщение об ошибке:

Error in duplicated.data.table(z_rbind) : data table must have keys

Код работает как есть для фреймов данных, хотя я назвал каждую функцию с шаблоном dt_operation,

Есть ли способ обойти эту проблему? Установка ключей работает только для целых чисел, что является ограничением, которое я не могу принять для входных данных. Итак, может быть, мне не хватает умного способа использования таблиц данных?


Пример функций операций над множествами, где элементами множеств являются строки данных:

dt_unique       <- function(x){
    return(unique(x))
}

dt_union        <- function(x,y){
    z_rbind     <- rbind(x,y)
    z_unique    <- dt_unique(z_rbind)
    return(z_unique)
}

dt_intersect    <- function(x,y){
    zx          <- dt_unique(x)
    zy          <- dt_unique(y)

    z_rbind     <- rbind(zy,zx)
    ixDupe      <- which(duplicated(z_rbind))
    z           <- z_rbind[ixDupe,]
    return(z)
}

dt_setdiff      <- function(x,y){
    zx          <- dt_unique(x)
    zy          <- dt_unique(y)

    z_rbind     <- rbind(zy,zx)
    ixRangeX    <- (nrow(zy) + 1):nrow(z_rbind)
    ixNotDupe   <- which(!duplicated(z_rbind))
    ixDiff      <- intersect(ixNotDupe, ixRangeX)
    diffX       <- z_rbind[ixDiff,]
    return(diffX)
}

Примечание 1. Одно из предполагаемых применений этих вспомогательных функций - найти строки, в которых значения ключа в x не входят в число значений ключа в y. Таким образом, я могу найти, где могут появиться NA при расчете x[y] или же y[x], Хотя это использование позволяет устанавливать ключи для z_rbind объект, я бы предпочел не ограничивать себя только этим вариантом использования.

Примечание 2: Для связанных постов, вот пост о запуске unique на фреймах данных, с отличными результатами для запуска с обновленным data.table пакет. И это более ранний пост о запуске unique на таблицах данных.

1 ответ

Решение

duplicated.data.table нужно такое же исправление unique.data.table получил [РЕДАКТИРОВАТЬ: Теперь сделано в v1.7.2]. Пожалуйста, подайте еще один отчет об ошибке: bug.report(package="data.table"), Для удобства других пользователей вы уже используете v-1.6.7 от R-Forge, а не 1.6.6 для CRAN.

Но в Примечании 1 есть идиома "не присоединяться":

x[-x[y,which=TRUE]]

См. Также FR # 1384 (Новые аргументы not и whatna?), Чтобы упростить это для пользователей, а также ссылки на ключи, которые не соответствуют потоку, что более подробно описано.


Обновление Теперь в v1.8.3 реализовано not-join.

DT[-DT["a",which=TRUE,nomatch=0],...]   # old idiom
DT[!"a",...]                            # same result, now preferred.
Другие вопросы по тегам