将data.table有条件地划分为子表到列值

时间:2013-04-16 11:57:23

标签: r split data.table

此问题与同名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

从刚才显示的例子可以推断,分裂条件是:

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

重要:在此示例中,“value”一词必须用作列值的几个。

注意

我认为这个输出结构就是那样(第二个目标)我必须将一个(或两个)函数应用于这个子表,得到它们的输出并聚合它们(例如sum,merge或其他操作)通过元素列表的通用名称(即0|00|01|01|0等等。)

如果您认为有更好的适合或更容易的输出结构也允许第二个目标,那么您的建议非常受欢迎。

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

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

所以非常感谢您的帮助,因为它将帮助我学习新的东西。提前谢谢。

1 个答案:

答案 0 :(得分:3)

我会使用rlesplit执行此操作,如下所示:

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

阅读您的笔记部分,因为您的目标是通过分组/聚合 将功能应用于这些子表,我建议您只添加一个额外的列{ {1}}喜欢这样:

data.table

如果您愿意,还可以添加其他分组:

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

现在,如果您希望将所有“0 | 0”组合在一起,则按datat[, grp2 := rep(seq_along(rle.ids$values), rle.ids$lengths)] 进行子集化。

grp1

如果要对每个单独的“0 | 0”集合进行聚合,则按# example datat[, list(s.A = sum(A)), by = grp1] 进行子集化。

grp2

希望这有帮助。