【问题标题】:Is there a fast way to turn a data table into a list of data tables?有没有一种快速的方法可以将数据表转换为数据表列表?
【发布时间】:2020-09-10 04:27:26
【问题描述】:

我有一个具有此架构的数据表:

date, key_a, key_b, key_c, key_d, value

我想制作一个具有这种结构的列表:

[1]
date, key_a, value

[2] 
date, key_b, value

[3]
date, key_c, value

我想将我的 dt 聚合到一个列表中,其中每个条目都将 dt 聚合到一个单独的键中。

这是我的代码

setDT(dt)

list_of_dts[1] <- 
    dt[, .(value = sum(value)), .(date, key_a)]

list_of_dts[2] <- 
    dt[, .(value = sum(value)), .(date, key_b)]

(So on)

有没有更有效的方法来解决这个问题?

【问题讨论】:

  • Cauder,您当然关心大型表的性能。 data.table 提供的速度和效率在数据驻留在一个地方时很有用;然而,当分割一个框架时,它会将单个位置的对象分割成多个对象,这通常涉及数据的复制(这是data.table 仅作为最后手段所做的事情)。当您在所有列出的表中都有"date""value" 时,您的大部分数据都会被按定义复制。

标签: r datatable data.table


【解决方案1】:

也许获取长格式的数据,然后总结它:

library(data.table)
setDT(dt)
dt1 <- melt(dt, id.vars = c('date', 'value'))
dt1 <- dt1[, .(value = sum(value)), .(date, variable)]

现在,如果您想要数据框列表,您可以使用 split

split(dt1, dt1$variable)

【讨论】:

  • split 是否利用了数据表的速度优势?
  • @Cauder - 现在有一段时间,我认为有一个特定的 split.data.table 函数已经过优化 - 请参阅 stackoverflow.com/questions/14977997/split-data-table
  • 还要考虑您是否真的想首先拆分数据。你这样做的目的是什么?
  • 我有一个单独的列,我想将它单独聚合到一堆其他列中。计算将是昂贵的 b/c 它是 50GB
【解决方案2】:

我们可以使用tidyverse

library(dplyr)
library(tidyr)
dt %>%
    pivot_longer(cols = starts_with('key'), values_to = 'value1') %>%
    group_by(date, name) %>%
     summarise(value = sum(value1))

一种选择是转换为disk.frame 并按操作进行分组

library(disk.frame)
dt %>%
    pivot_longer(cols = starts_with('key'), values_to = 'value1') %>%
    as.disk.frame %>%
    group_by(date, name) %>%
    summarise(value = sum(value1)) %>%
    collect()

当有多个.csv文件时,可以直接用csv_to_disk.frame读取

df  <- csv_to_disk.frame(file.path(tempdir(), "df.csv"), 
  inmapfn = function(chunk) {
   # convert to date_str to date format and store as "date"
       chunk[, date := as.Date(date_str, "%Y-%m-%d")]
       chunk[, date_str:= NULL]
       chunk[, new  := col1 + 5]
    })

【讨论】:

  • 我担心速度,因为我的数据表有 800M 行。我可以通过利用数据表的方式来做到这一点吗?
  • @Cauder 考虑使用disk.frame 它很快
【解决方案3】:

试试这个data.table-native 尝试:

dt <- data.table(date=c(1,1,2), key_a=c(11,11,13), key_b=c(21,21,23), key_c=c(31,31,33), key_d=c(41,41,43), value=c(51,51,53))
keynames <- grep("^key", colnames(dt), value = TRUE)
othnames <- setdiff(colnames(dt), keynames)
keynames
# [1] "key_a" "key_b" "key_c" "key_d"
othnames
# [1] "date"  "value"

原始数据的拆分:

lapply(setNames(nm = keynames), function(kn) subset(dt, select = c(othnames, kn)))
# $key_a
#    date value key_a
# 1:    1    51    11
# 2:    1    51    11
# 3:    2    53    13
# $key_b
#    date value key_b
# 1:    1    51    21
# 2:    1    51    21
# 3:    2    53    23
# $key_c
#    date value key_c
# 1:    1    51    31
# 2:    1    51    31
# 3:    2    53    33
# $key_d
#    date value key_d
# 1:    1    51    41
# 2:    1    51    41
# 3:    2    53    43

或者对于您的聚合问题:

lapply(setNames(nm = keynames), function(kn) dt[, .(value = sum(value)), by = c("date", kn)])
# $key_a
#    date key_a value
# 1:    1    11   102
# 2:    2    13    53
# $key_b
#    date key_b value
# 1:    1    21   102
# 2:    2    23    53
# $key_c
#    date key_c value
# 1:    1    31   102
# 2:    2    33    53
# $key_d
#    date key_d value
# 1:    1    41   102
# 2:    2    43    53

【讨论】:

    猜你喜欢
    • 2020-01-11
    • 2014-08-20
    • 2021-12-13
    • 2021-01-09
    • 2013-09-15
    • 2010-10-01
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    相关资源
    最近更新 更多