r语言 - 使用 data.table 为行块创建组标签



我有类似于以下数据集的东西:

myDT <- structure(list(domain = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), id = 2:22, L1 = 2:22), row.names = c(NA, 
-21L), class = c("data.table", "data.frame"))

我想创建一个新的列L2,为domain内的每 2 行创建一个索引。但是,如果存在余数,例如在domain=2id=8,9,10的情况下,那么只要它们在同一domain内,这些id就应该一起索引。请注意,玩具数据集中的特定id值是连续的,并不总是如图所示。输出将是:

structure(list(domain = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), id = 2:22, L1 = 2:22, L2=c(1L,1L,2L,2L,3L,3L,4L,4L,4L,
                                  5L,5L,6L,6L,7L,7L,8L,8L,9L,9L,10L,10L)), 
row.names = c(NA, -21L), class = c("data.table", "data.frame"))

有没有一种有效的方法可以在data.table中做到这一点?

我尝试在子集调用中使用.N/rowid和整数除法运算符%/%(因为每n行应该给出相同的值(,但它让我无处可去。例如,我尝试了类似的东西:

myDT[, L2 := rowid(domain)%/%2]

但显然,这并不能满足以下要求:domain=2中的最后 3 行具有相同的索引,并且索引应继续递增domain=3

编辑请参阅修订后的所需输出数据表和相应的说明。

编辑 2

以下是myDT的附加版本:

myDT2 <- structure(list(domain = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 5L, 5L, 
5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L), id = 2:40, 
L1 = 2:40), row.names = c(NA, -39L), class = c("data.table", 
"data.frame"))

当我在上面运行@chinsoon12的代码时,我得到:

structure(list(domain = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 5L, 5L, 
5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L), id = 2:40, 
L1 = 2:40, L2 = c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L, 4L, 5L, 
5L, 6L, 6L, 7L, 7L, 8L, 8L, 9L, 9L, 10L, 10L, 11L, 11L, 11L, 
11L, 12L, 12L, 13L, 13L, 14L, 14L, 15L, 15L, 16L, 16L, 17L, 
17L, 18L, 18L)), row.names = c(NA, -39L), class = c("data.table", 
"data.frame"))

L2=11似乎有 4 个值,而其中两个应该是 12,因为它们在不同的域中。

一个想法是创建一个自定义函数,该函数将根据每个组的长度和该长度的剩余部分(除以 2 时(创建顺序向量。函数是,

f1 <- function(x) {
v1 <- length(x)
i1 <- rep(seq(floor(v1 / 2)), each = 2)
i2 <- c(i1, rep(max(i1), v1 %% 2))
i2 + seq_along(i2)
}

我尝试通过data.table应用它,但我收到有关错误的错误,所以这里是基本 R,

cumsum(c(TRUE, diff(with(myDT2, ave(id, domain, FUN = f1))) != 1))
#[1]  1  1  2  2  3  3  4  4  4  5  5  6  6  7  7  8  8  9  9 10 10 11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19

这是为编辑的问题更新的另一种方法(灵感来自@Sotoscumsum的使用(:

  1. 对于每个domainid,创建一个重复的序列1, 0, 1, 0, 1, ...,默认情况下将最终序列元素设置为零。
  2. domainid 对创建的序列进行cumsum
library(data.table)
setDT(myDT2)
myDT2[, L2 := c(head(rep_len(c(1, 0), .N), -1), 0), by = domain][, L2 := cumsum(L2)][]
#>     domain id L1 L2
#>  1:      2  2  2  1
#>  2:      2  3  3  1
#>  3:      2  4  4  2
#>  4:      2  5  5  2
#>  5:      2  6  6  3
#>  6:      2  7  7  3
#>  7:      2  8  8  4
#>  8:      2  9  9  4
#>  9:      2 10 10  4
#> 10:      3 11 11  5
#> 11:      3 12 12  5
#> 12:      3 13 13  6
#> 13:      3 14 14  6
#> 14:      3 15 15  7
#> 15:      3 16 16  7
#> 16:      3 17 17  8
#> 17:      3 18 18  8
#> 18:      3 19 19  9
#> 19:      3 20 20  9
#> 20:      3 21 21 10
#> 21:      3 22 22 10
#> 22:      4 23 23 11
#> 23:      4 24 24 11
#> 24:      5 25 25 12
#> 25:      5 26 26 12
#> 26:      5 27 27 13
#> 27:      5 28 28 13
#> 28:      5 29 29 14
#> 29:      5 30 30 14
#> 30:      5 31 31 15
#> 31:      5 32 32 15
#> 32:      5 33 33 16
#> 33:      5 34 34 16
#> 34:      5 35 35 17
#> 35:      5 36 36 17
#> 36:      5 37 37 18
#> 37:      5 38 38 18
#> 38:      5 39 39 19
#> 39:      5 40 40 19
#>     domain id L1 L2

以下是 2 以外的可变重复次数的另一个选项:

n <- 4
setDT(myDT)[, L2 := 
myDT[, {
x <- ceiling(seq_along(id)/n)
if (sum(x==x[.N]) < n) x[x==x[.N]] <- floor(.N/n)
x
}, domain][, rleid(domain, V1)]
]

或者递归方法:

n <- 4
s <- 0
setDT(myDT)[, L2 := 
myDT[, {
x <- s + ceiling(seq_along(id)/n)
if (sum(x==x[.N]) < n) x[x==x[.N]] <- s + floor(.N/n)
s <- if (s<max(x)) max(x) else s + 1
x
}, domain]$V1
]

n=2输出:

domain id L1 L2
1:      2  2  2  1
2:      2  3  3  1
3:      2  4  4  2
4:      2  5  5  2
5:      2  6  6  3
6:      2  7  7  3
7:      2  8  8  4
8:      2  9  9  4
9:      2 10 10  4
10:      3 11 11  5
11:      3 12 12  5
12:      3 13 13  6
13:      3 14 14  6
14:      3 15 15  7
15:      3 16 16  7
16:      3 17 17  8
17:      3 18 18  8
18:      3 19 19  9
19:      3 20 20  9
20:      3 21 21 10
21:      3 22 22 10
22:      4 23 23 11
23:      4 24 24 11
24:      5 25 25 12
25:      5 26 26 12
26:      5 27 27 13
27:      5 28 28 13
28:      5 29 29 14
29:      5 30 30 14
30:      5 31 31 15
31:      5 32 32 15
32:      5 33 33 16
33:      5 34 34 16
34:      5 35 35 17
35:      5 36 36 17
36:      5 37 37 18
37:      5 38 38 18
38:      5 39 39 19
39:      5 40 40 19
domain id L1 L2

n=4输出:

domain id L1 L2
1:      2  2  2  1
2:      2  3  3  1
3:      2  4  4  1
4:      2  5  5  1
5:      2  6  6  2
6:      2  7  7  2
7:      2  8  8  2
8:      2  9  9  2
9:      2 10 10  2
10:      3 11 11  3
11:      3 12 12  3
12:      3 13 13  3
13:      3 14 14  3
14:      3 15 15  4
15:      3 16 16  4
16:      3 17 17  4
17:      3 18 18  4
18:      3 19 19  5
19:      3 20 20  5
20:      3 21 21  5
21:      3 22 22  5
22:      4 23 23  6
23:      4 24 24  6
24:      5 25 25  7
25:      5 26 26  7
26:      5 27 27  7
27:      5 28 28  7
28:      5 29 29  8
29:      5 30 30  8
30:      5 31 31  8
31:      5 32 32  8
32:      5 33 33  9
33:      5 34 34  9
34:      5 35 35  9
35:      5 36 36  9
36:      5 37 37 10
37:      5 38 38 10
38:      5 39 39 10
39:      5 40 40 10
domain id L1 L2

最新更新