gpt4 book ai didi

r - 使用 data.table 快速取消嵌套

转载 作者:行者123 更新时间:2023-12-04 02:25:23 26 4
gpt4 key购买 nike

我目前正在使用 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.frame 相当敏感s 或 data.table 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
创建于 2021-06-22 由 reprex package (v1.0.0)
在我的实际用例中,我嵌套了 data.frame s 因为它来自用 RcppSimdJson 解析的 JSON和这里 tidyr是比较快的。

最佳答案

只是做一个基准,显示与 data.table 的解决方案的差异和 tidyr以另一种方式给出 data.table和一个 base解决方案。

DT <- data.table::data.table(
a = c("a1", "a2"),
df1 = list(data.frame(
b = c("b1", "b2")
))
)
n <- 1e5
set.seed(42)
dt1 <- DT[sample(seq_len(nrow(DT)), n, TRUE),]

bench::mark(check = FALSE
, tidyr = tidyr::unnest(dt1, df1)
, dt = dt1[, data.table::rbindlist(df1), by = .(a)]
, dt2 = dt1[, unlist(df1, TRUE, FALSE), .(a)]
, base = data.frame(a=rep(dt1$a, lapply(dt1$df1, nrow)), do.call(rbind, dt1$df1))
, base2 = data.frame(a=rep(dt1$a, lapply(dt1$df1, nrow)), b=unlist(dt1$df1, TRUE, FALSE))
)
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl>
#1 tidyr 1.03s 1.03s 0.971 22.59MB 7.76 1 8
#2 dt 46.9ms 50.15ms 17.1 15.01MB 9.47 9 5
#3 dt2 11.66ms 13.66ms 70.8 14.03MB 35.4 36 18
#4 base 3.47s 3.47s 0.288 43.23MB 12.1 1 42
#5 base2 353.9ms 363.41ms 2.75 4.58MB 11.0 2 8
所以 data.table两种方式中最快的,其次是一种 base解决方案,然后 tidyr然后是另一个 base解决方案。

关于r - 使用 data.table 快速取消嵌套,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68080021/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com