[Обновление 1: как заметил Мэтью Доул, я использую data.table
версию 1.6.7 на R-Forge, а не на CRAN. Вы не увидите такого же поведения с более ранней версией data.table
.]
В качестве фона: я переношу некоторые небольшие служебные функции для выполнения операций над строками фрейма данных или парами фреймов данных (т.е. каждая строка является элементом набора), например. уникальный - для создания набора из списка, объединения, пересечения, разности наборов и т. д. Они имитируют intersect(...,'rows')
, setdiff(...,'rows')
и т. д. Matlab, которые, похоже, не имеют аналогов в 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
на таблицы данных.