Извлечение уникальных строк из таблицы данных в R

Я мигрирую из фреймов данных и матриц в таблицы данных, но не нашел решения для извлечения уникальных строк из таблицы данных. Я предполагаю, что что-то мне не хватает в [,J] примечание, хотя я еще не нашел ответ в FAQ и интро виньетках. Как я могу извлечь уникальные строки, не преобразовывая обратно во фреймы данных?

Вот пример:

library(data.table)
set.seed(123)
a <- matrix(sample(2, 120, replace = TRUE), ncol = 3)
a <- as.data.frame(a)
b <- as.data.table(a)

# Confirm dimensionality
dim(a) # 40  3
dim(b) # 40  3

# Unique rows using all columns
dim(unique(a))  # 8 3
dim(unique(b))  # 34 3

# Unique rows using only a subset of columns
dim(unique(a[,c("V1","V2")]))   # 4 2
dim(unique(b[,list(V1,V2)]))    # 29 2

Смежный вопрос: является ли это поведение результатом несортировки данных, как в Unix uniq функционировать?

2 ответа

Решение

До data.table v1.9.8 поведение по умолчанию unique.data.table Метод состоял в том, чтобы использовать ключи для определения столбцов, по которым должны быть возвращены уникальные комбинации. Если key было NULL (по умолчанию), можно получить исходный набор данных обратно (как в ситуации с ОП).

По состоянию на data.table 1.9.8+, unique.data.table Метод использует все столбцы по умолчанию, что соответствует unique.data.frame в базе R. Для этого используйте ключевые столбцы, явно передать by = key(DT) в unique (замена DT в вызове ключа с именем data.table).

Следовательно, старое поведение было бы что-то вроде

library(data.table) v1.9.7-
set.seed(123)
a <- as.data.frame(matrix(sample(2, 120, replace = TRUE), ncol = 3))
b <- data.table(a, key = names(a))
## key(b)
## [1] "V1" "V2" "V3"
dim(unique(b)) 
## [1] 8 3

В то время как для data.table v1.9.8+, просто

b <- data.table(a) 
dim(unique(b)) 
## [1] 8 3
## or dim(unique(b, by = key(b)) # in case you have keys you want to use them

Или без копии

setDT(a)
dim(unique(a))
## [1] 8 3

Как упоминал Сет, пакет data.table эволюционировал и теперь предлагает оптимизированные функции для этого.

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

uniqueN(a)

И если вы хотите выбрать только подмножество столбцов, вы можете использовать аргумент "by":

uniqueN(a,by = c('V1','V2'))

РЕДАКТИРОВАТЬ: Как упоминалось в комментариях, это будет только количество уникальных строк. Чтобы получить уникальные значения, используйте уникальные вместо:

unique(a)

И для подмножества:

unique(a[c('V1',"V2")], by=c('V1','V2'))

Другие вопросы по тегам