如何在 R 中使用 data.table 保持唯一的列表列值?
How to keep unique list-column values using data.table in R?
我有一个数据框,它用一个 ID 标识一组值。比方说:
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)
)
如您所见,一个 id 标识多行值,而不是单个值。我想要做的是只保留标识一组值的第一次出现的 id。例如,上面数据框中的 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))]
我在这上面花了很多时间,但我似乎无法弄清楚如何实现我想要的。我不一定依附于“nest -> keep unique dataframe”路径,但这是解决我能想到的问题的唯一方法。
我们可以使用 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
我有一个数据框,它用一个 ID 标识一组值。比方说:
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)
)
如您所见,一个 id 标识多行值,而不是单个值。我想要做的是只保留标识一组值的第一次出现的 id。例如,上面数据框中的 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))]
我在这上面花了很多时间,但我似乎无法弄清楚如何实现我想要的。我不一定依附于“nest -> keep unique dataframe”路径,但这是解决我能想到的问题的唯一方法。
我们可以使用 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