【问题标题】:Divide a data.table into sub-tables conditionally to column values根据列值有条件地将 data.table 划分为子表
【发布时间】:2013-04-16 11:57:23
【问题描述】:

这个问题与data.table类有关,来自同名的R包。

给定一个data.table对象,我想根据它的一些列的值把它分成切片。

为了说明我必须做什么,我举个例子。

假设这是输入data.table

dataf <- data.frame(list(
  T = c(1.80,1.81,1.82,1.83,1.85,1.87,1.90,1.95,2.00),
  A = c(1,0,1,1,1,0,1,1,0),
  B = c(0,0,0,0,0,0,1,0,0),
  C = c(0,1,0,1,1,0,1,1,0),
  D = c(0,0,1,1,1,0,0,1,0))
)
datat <- data.table(dataf)
datat
#       T A B C D
# 1: 1.80 1 0 0 0
# 2: 1.81 0 0 1 0
# 3: 1.82 1 0 0 1
# 4: 1.83 1 0 1 1
# 5: 1.85 1 0 1 1
# 6: 1.87 0 0 0 0
# 7: 1.90 1 1 1 0
# 8: 1.95 1 0 1 1
# 9: 2.00 0 0 0 0

目标是根据n选中列(与n = 0, ..., ncol(datat) - 1)的值,将这个表拆分成子表。

对于此输入,选择锚列 CD,输出必须类似于:

# $`0|0`
#       T A B C D
# 1: 1.80 1 0 0 0

# $`1|0`
#       T A B C D
# 1: 1.81 0 0 1 0

# $`0|1`
#       T A B C D
# 1: 1.82 1 0 0 1

# $`1|1`
#       T A B C D
# 1: 1.83 1 0 1 1
# 2: 1.85 1 0 1 1

# $`0|0`
#       T A B C D
# 1: 1.87 0 0 0 0

# $`1|0`
#       T A B C D
# 1: 1.90 1 1 1 0

# $`1|1`
#       T A B C D
# 1: 1.95 1 0 1 1

# $`0|0`
#       T A B C D
# 1: 2.00 0 0 0 0

从刚才的例子可以推导出,分裂条件是:

  • 所选列的值与上一行的值不同?

重要提示:在本例中,“值”一词必须用作一对列值。

注意

我当时认为这个输出结构(第二个目标)我必须对这个子表应用一个(或两个)函数,获取它们的输出并聚合它们(例如求和、合并或其他操作)通过元素列表的通用名称(即0|00|01|01|0 等等等等)。

如果您认为有一个更合适或更简单的输出结构也可以实现第二个目标,我们非常欢迎您提出建议。

显然,解决方案的性能很重要,因为我必须处理大表。

不幸的是,我认为自己是 data.table 包的新手,事实上我只知道几件事:如何通过 colnames 进行子集化等。

非常感谢您的帮助,因为它将帮助我学习新知识。提前致谢。

【问题讨论】:

    标签: r split data.table


    【解决方案1】:

    我会用rlesplit 来做,如下所示:

    ids <- do.call(paste, c(datat[, 4:5], sep="|"))
    rle.ids <- rle(ids)
    datat.spl <- split(datat, rep(seq_along(rle.ids$values), rle.ids$lengths))
    names(datat.spl) <- rle.ids$values
    

    阅读您的注释部分,因为您的目标是通过分组/聚合这些子表应用函数,我建议只在@添加一个附加列987654324@这样的:

    datat[, grp1 := do.call(paste, c(datat[, 4:5], sep="|"))]
    

    如果你愿意,你也可以像这样添加另一个分组:

    datat[, grp2 := rep(seq_along(rle.ids$values), rle.ids$lengths)]
    

    现在,如果您希望将所有“0|0”组合在一起,则按grp1 进行子集化。

    # example
    datat[, list(s.A = sum(A)), by = grp1]
    

    如果您希望对每个单独的“0|0”集进行聚合,则使用grp2 的子集。

    # example
    datat[, list(grp1 = grp1[1], s.A = sum(A)), by = grp2]
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多