说我有以下data.table:
library(data.table)
DT <- data.table(R=sample(0:1, 10000, rep=TRUE), Seq=0)
Run Code Online (Sandbox Code Playgroud)
返回的内容如下:
R Seq
1: 1 0
2: 1 0
3: 0 0
4: 0 0
5: 1 0
---
9996: 1 0
9997: 0 0
9998: 0 0
9999: 0 0
10000: 1 0
Run Code Online (Sandbox Code Playgroud)
我想生成一个序列(1,2,3,...,n),只要R从前一行改变,它就会重置.想想它就像我在计算一连串随机数.
那么上面会是这样的:
R Seq
1: 1 1
2: 1 2
3: 0 1
4: 0 2
5: 1 1
---
9996: 1 5
9997: 0 1
9998: 0 2
9999: 0 3
10000: 1 2
Run Code Online (Sandbox Code Playgroud)
思考?
这是一个选项:
set.seed(1)
DT <- data.table(R=sample(0:1, 10000, rep=TRUE), Seq=0L)
DT[, Seq:=seq(.N), by=list(cumsum(c(0, abs(diff(R)))))]
DT
Run Code Online (Sandbox Code Playgroud)
我们创建一个计数器,每当你的0-1变量使用时,它就会递增cumsum(abs(diff(R))).这c(0,部分是为了确保我们得到正确的长度向量.然后我们用它分开by.这会产生:
R Seq
1: 0 1
2: 0 2
3: 1 1
4: 1 2
5: 0 1
---
9996: 1 1
9997: 0 1
9998: 1 1
9999: 1 2
10000: 1 3
Run Code Online (Sandbox Code Playgroud)
编辑:解决澄清请求:
让我们看看我正在使用的计算by,分解为两个新列:
DT[, diff:=c(0, diff(R))]
DT[, cumsum:=cumsum(abs(diff))]
print(DT, topn=10)
Run Code Online (Sandbox Code Playgroud)
生产:
R Seq diff cumsum
1: 0 1 0 0
2: 0 2 0 0
3: 1 1 1 1
4: 1 2 0 1
5: 0 1 -1 2
6: 1 1 1 3
7: 1 2 0 3
8: 1 3 0 3
9: 1 4 0 3
10: 0 1 -1 4
---
9991: 1 2 0 5021
9992: 1 3 0 5021
9993: 1 4 0 5021
9994: 1 5 0 5021
9995: 0 1 -1 5022
9996: 1 1 1 5023
9997: 0 1 -1 5024
9998: 1 1 1 5025
9999: 1 2 0 5025
10000: 1 3 0 5025
Run Code Online (Sandbox Code Playgroud)
您可以看到每次R改变时,diff的绝对值的累积和如何递增1.然后我们可以使用该cumsum列分解data.table成块,并为每个块生成一个序列,使用seq(.N)该序列计算块中的项目数(.N正好表示每个by组中的项目数).