2013-04-16 34 views
2

此问题与data.table类有关,来自同名的R包。将data.table有条件划分为列值

给定一个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|0,1|01|0等)。

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

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

不幸的是,我认为自己有data.table包一个新手,事实上我知道它只有几件事情:如何通过colnames等等等,以子集..

所以你的帮助是极大的赞赏,因为它会帮助我学习新的东西。提前致谢。

回答

3

我会跟rle如下做到这一点,split

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 

读你的笔记部分,因为你的目标是通过分组应用功能这些子表/聚合他们,我建议只是增加一个额外的列data.table像这样:

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

如果你愿意,你还可以添加像这样的另一个分组:如果你希望所有的

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

现在|组合在一起,“0”,然后通过grp1子集。通过grp2,然后,子|

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

如果你想聚集为每个单独设置“0”来完成。

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

希望这会有所帮助。