У меня есть фрейм данных, который идентифицирует набор значений с идентификатором. Скажем:
library(data.table)
dt <- data.table(
id = rep(c("a", "b", "c"), each = 2),
value1 = c(1, 1, 1, 2, 1, 1),
value2 = c(0, 3, 0, 3, 0, 3)
)
Как видите, идентификатор идентифицирует множество строк значений, а не одну. Что я хочу сделать, так это сохранить только те идентификаторы, которые идентифицируют первое вхождение группы значений. Например, a
и c
в фрейме данных выше определяют одну и ту же группу значений, поэтому я бы хотел, чтобы результат был:
dt[1:4] # desired output
#> id value1 value2
#> 1: a 1 0
#> 2: a 1 3
#> 3: b 1 0
#> 4: b 2 3
Я понял, что простым способом сделать это было бы также вложить группу значений в фреймы данных, а затем сохранить только уникальные записи на основе этого нового вложенного столбца фрейма данных. Вложение делается достаточно просто:
dt <- dt[, .(data = list(.SD)), by = id]
dt
#> id data
#> 1: a <data.table[2x2]>
#> 2: b <data.table[2x2]>
#> 3: c <data.table[2x2]>
Но фактическое «сохранение уникальных вхождений», по-видимому, довольно сложно. Я попробовал два разных подхода, но оба они потерпели неудачу. Во-первых, используя unique.data.table
. Но аргумент by
еще не поддерживает столбцы списка:
dt <- unique(dt, by = "data")
#> Error in forderv(x, by = by, sort = FALSE, retGrp = TRUE): Column 1 passed to [f]order is type 'list', not yet supported.
А затем использую .I[]
, но тогда я не могу передать столбец списка аргументу by
:
dt <- dt[dt[, .I[1], by = data]$V1]
#> Error: column or expression 1 of 'by' or 'keyby' is type list. Do not quote column names. Usage: DT[,sum(colC),by=list(colA,month(colB))]
Я потратил довольно много времени на это, но я не могу понять, как достичь того, чего я хочу. Я не обязательно привязан к пути «гнездо -> сохранить уникальный фрейм данных», но это единственный способ решить проблему, которую я мог придумать.
Мы можем использовать duplicated
с unnest
library(tidyr)
dt[, .(data = list(.SD)), by = id][!duplicated(data)] %>%
unnest(data)
-выход
# A tibble: 4 × 3
id value1 value2
<chr> <dbl> <dbl>
1 a 1 0
2 a 1 3
3 b 1 0
4 b 2 3
В духе ответа @akrun, но сохраняя data.table
как единственную зависимость:
library(data.table)
dt <- data.table(
id = rep(c("a", "b", "c"), each = 2),
value1 = c(1, 1, 1, 2, 1, 1),
value2 = c(0, 3, 0, 3, 0, 3)
)
dt <- dt[, .(data = list(.SD)), by = id]
dt <- dt[!duplicated(data)]
dt[, unlist(data, recursive = FALSE), by = id]
#> id value1 value2
#> 1: a 1 0
#> 2: a 1 3
#> 3: b 1 0
#> 4: b 2 3
Да,
duplicated()
делает свое дело. Я добавил ответ, который добавляет собственный способ распаковки data.table, но вы решили проблему!