【发布时间】:2021-09-05 20:08:35
【问题描述】:
我目前正在使用tidyr 包来取消嵌套列表列。但是,我正在寻找一种更快的方法并转向data.table(我是菜鸟)。考虑以下示例:
dt1 <- data.table::data.table(
a = c("a1", "a2"),
df1 = list(data.frame(
b = c("b1", "b2")
))
)
tidyr::unnest(dt1, df1)
#> # A tibble: 4 x 2
#> a b
#> <chr> <chr>
#> 1 a1 b1
#> 2 a1 b2
#> 3 a2 b1
#> 4 a2 b2
dt1[, data.table::rbindlist(df1), by = .(a)]
#> a b
#> 1: a1 b1
#> 2: a1 b2
#> 3: a2 b1
#> 4: a2 b2
Created on 2021-06-22 by the reprex package (v1.0.0)
我得到了相同的结果,但是如果我有一个大的 data.table 并且在 by 中有更多的列,那么这种方法在 data.table 中的性能比在 tidyr 中的性能更差。可以缓解吗?
一个后续问题是如何使用data.table 取消嵌套多个列。考虑这个例子:
dt2 <- data.table::data.table(
a = c("a1", "a2"),
df1 = list(data.frame(
b = c("b1", "b2")
)),
df2 = list(data.frame(
c = c("c1", "c2")
))
)
tidyr::unnest(dt2, c(df1, df2))
#> # A tibble: 4 x 3
#> a b c
#> <chr> <chr> <chr>
#> 1 a1 b1 c1
#> 2 a1 b2 c2
#> 3 a2 b1 c1
#> 4 a2 b2 c2
Created on 2021-06-22 by the reprex package (v1.0.0)
在data.table::rbindlist 中使用多个参数似乎不起作用。
更新:在做了一个大的(r)示例来证明我对执行时间的主张后,tidyr 对列表列是否包含 data.frames 或 @987654334 非常敏感@s:
n_inner <- 300
inner_df <- data.frame(
d1 = seq.POSIXt(as.POSIXct("2020-01-01"), as.POSIXct("2021-01-01"), length.out = n_inner),
d2 = seq.POSIXt(as.POSIXct("2020-01-01"), as.POSIXct("2021-01-01"), length.out = n_inner),
d3 = rnorm(n_inner)
)
n_outer <- 400
dt <- data.table::data.table(
a = sample(10, n_outer, replace = TRUE),
b = seq.POSIXt(as.POSIXct("2020-01-01"), as.POSIXct("2021-01-01"), length.out = n_outer),
c = seq.POSIXt(as.POSIXct("2019-01-01"), as.POSIXct("2020-01-01"), length.out = n_outer),
d = rep(list(inner_df), n_outer)
)
bench::mark(check = FALSE,
tidyr = tidyr::unnest(dt, d),
datatable = dt[, data.table::rbindlist(d), by = .(a, b, c)]
)
#> # A tibble: 2 x 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 tidyr 14ms 18.7ms 53.2 18MB 26.6
#> 2 datatable 56.2ms 56.2ms 17.8 25.5MB 178.
inner_dt <- data.table::as.data.table(inner_df)
dt$d <- rep(list(inner_dt), n_outer)
bench::mark(check = FALSE,
tidyr = tidyr::unnest(dt, d),
datatable = dt[, data.table::rbindlist(d), by = .(a, b, c)]
)
#> Warning: Some expressions had a GC in every iteration; so filtering is disabled.
#> # A tibble: 2 x 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 tidyr 202.2ms 209.3ms 4.40 28.4MB 19.1
#> 2 datatable 43.5ms 49.9ms 18.3 25.4MB 22.0
由reprex package (v1.0.0) 于 2021 年 6 月 22 日创建
在我的实际用例中,我嵌套了data.frames,因为它来自用RcppSimdJson 解析的JSON,而这里tidyr 更快。
【问题讨论】:
-
您能否举一个示例数据集,其中可以观察到
data.table的这种不良性能?
标签: r data.table unnest