通过多个分组顺序变量折叠和粘贴文本

collapse and paste text by multiple grouping sequential variables

我有包含分组变量和文本的行。我想用data.table在连续n次分组变量都相同的情况下粘贴文本

这是我的:

       x y                              z
 1:  Pre A Lorem ipsum dolor sit amet, ac
 2:  Pre C Maecenas netus in, lacus fames
 3:  Pre C Conubia sed nulla dolor dui ap
 4:  Pre A Eget laoreet eros in aliquet e
 5:  Pre A Vestibulum quisque himenaeos p
 6: Post A Sed venenatis. Ante turpis ege
 7: Post A Ultricies ultricies eleifend m
 8: Post B Conubia in in sed etiam nec mo
 9: Post A Quam nec ex sodales dictum orc
10: Post A Sed ante id pulvinar maximus s

期望的输出:

     x y                                                             z
1  Pre A                                Lorem ipsum dolor sit amet, ac
2  Pre C Maecenas netus in, lacus fames Conubia sed nulla dolor dui ap
3  Pre A Eget laoreet eros in aliquet e Vestibulum quisque himenaeos p
4 Post A Sed venenatis. Ante turpis ege Ultricies ultricies eleifend m
5 Post B                                Conubia in in sed etiam nec mo
6 Post A Quam nec ex sodales dictum orc Sed ante id pulvinar maximus s

MWE:

library(data.table)
library(stringi)

set.seed(12)
dat <- data.frame(
    x = rep(c("Pre", "Post"), each=5), 
    y = sample(LETTERS[1:3], 10, TRUE), 
    z = substring(stri_rand_lipsum(10), 1, 30), stringsAsFactors = FALSE
)

setDT(dat)

我们可以使用 data.table 的开发版本中的 rleid 来创建基于 'x' 和 'y' 变量的分组变量 ('gr') .按 'gr' 分组,我们得到 'x'、'y' 和 paste 的第一个元素以及 'z' 个元素。

library(data.table)#v1.9.5+
setDT(dat)[,list(x=x[1L], y= y[1L], z=paste(z, collapse = ' ')) ,
                      by = .(gr=rleid(x,y))][, gr:= NULL][]
#      x y                                                             z
#1:  Pre A                                Lorem ipsum dolor sit amet, ac
#2:  Pre C Maecenas netus in, lacus fames Conubia sed nulla dolor dui ap
#3:  Pre A Eget laoreet eros in aliquet e Vestibulum quisque himenaeos p
#4: Post A Sed venenatis. Ante turpis ege Ultricies ultricies eleifend m
#5: Post B                                Conubia in in sed etiam nec mo
#6: Post A Quam nec ex sodales dictum orc Sed ante id pulvinar maximus s

注意:安装开发版本的说明是 here


如果我们不使用开发版本,另一种选择是通过比较 pasteing 'x' 和 'y' 列之后的相邻元素来创建 'gr' 变量然后像以前一样进行。

setDT(dat)[, gr:={gr= paste(x,y); cumsum(c(TRUE, gr[-1]!= gr[-.N]))}]
res <- dat[, list(x=x[1L], y=y[1L], z=paste(z, collapse=' ')) ,
                     by = gr][,gr:= NULL][]
res
#      x y                                                             z
#1:  Pre A                                Lorem ipsum dolor sit amet, ac
#2:  Pre C Maecenas netus in, lacus fames Conubia sed nulla dolor dui ap
#3:  Pre A Eget laoreet eros in aliquet e Vestibulum quisque himenaeos p
#4: Post A Sed venenatis. Ante turpis ege Ultricies ultricies eleifend m
#5: Post B                                Conubia in in sed etiam nec mo
#6: Post A Quam nec ex sodales dictum orc Sed ante id pulvinar maximus s

这还会分配原始数据集中的 'gr' 列。我们可以将 'gr' 分配给 NULL 以保持原始结构相同。

dat[, gr:= NULL]

我们可以使用 'x'、'y' 和 'gr' 作为分组变量,而 return 仅使用 'z' 而不是 x=x[1L], y= y[1L] ]列。

res <- dat[,list(z=paste(z, collapse=' ')) ,.(x, y, gr)][, gr:= NULL][]
dat[, gr:= NULL]