首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据一定数量的连续零值对data.frame进行分段,并在R中给出顺序

如何根据一定数量的连续零值对data.frame进行分段,并在R中给出顺序
EN

Stack Overflow用户
提问于 2017-08-06 22:15:27
回答 1查看 97关注 0票数 1

我目前正在处理一辆车的数据。我们每5分钟记录一次汽车的速度,它包含了大量的零值。我的问题是,如何将数据分割成一个零值,并在R中给每个非零段一个有序数?让我们以一个示例数据为例:

代码语言:javascript
复制
sample <- data.frame(
  id = 1:15, 
  speed = c(50,0, 0, 30, 50, 40,0, 0, 25, 30, 50, 0, 30, 50, 40))

我想添加一个新列,为每个非零部分提供一个数字(从1开始),而是一个连续的k-零速度(或更多)编号为0。特别是对于这个示例数据,假设k等于2,那么我想要的结果应该类似于这个dataframe:

代码语言:javascript
复制
sample_new <- data.frame(
  id = 1:15, 
  speed = c(50,0, 0, 0, 50, 40,0, 0, 25, 30, 50, 0, 30, 50, 40), 
  number = c(1, 0, 0, 0, 2, 2, 0 ,0, 3, 3, 3, 3, 3, 3, 3))

打印为

代码语言:javascript
复制
   id speed number
1   1    50      1
2   2     0      0
3   3     0      0
4   4     0      0
5   5    50      2
6   6    40      2
7   7     0      0
8   8     0      0
9   9    25      3
10 10    30      3
11 11    50      3
12 12     0      3** <- here is the difference
13 13    30      3
14 14    50      3
15 15    40      3

我的数据中有100多万行,所以我希望这个解决方案在速度上是可以接受的。

设定"k“门槛的原因是,一些司机即使锁上汽车睡觉,也只会打开GPS。但在另一种情况下,当间隔小于k时,他们只是因为十字路口的灯光而停了下来。我想把注意力集中在长时间的止损上,而忽略短时的止损。

希望我的问题对you.Thank你有意义。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-07 00:16:33

由于处理速度是对超过1M行的生产数据集的关注,我建议使用data.table

很容易识别后续非零条目的组:

代码语言:javascript
复制
library(data.table)
setDT(sample)[, number := rleid(speed > 0 ) * (speed > 0)][]

id speed number 1: 1 50 1 2: 2 0 0 3: 3 0 0 4: 4 30 3 5: 5 50 3 6: 6 40 3 7: 7 0 0 8: 8 0 0 9: 9 25 5 10: 10 30 5 11: 11 50 5 12: 12 0 0 13: 13 30 7 14: 14 50 7 15: 15 40 7

组号不同,但没有连续编号。如果这是一个要求,它将变得棘手:

代码语言:javascript
复制
setDT(sample)[, number := as.integer(factor(rleid(speed > 0 ) * (speed > 0), exclude = 0))][]

id speed number 1: 1 50 1 2: 2 0 NA 3: 3 0 NA 4: 4 30 2 5: 5 50 2 6: 6 40 2 7: 7 0 NA 8: 8 0 NA 9: 9 25 3 10: 10 30 3 11: 11 50 3 12: 12 0 NA 13: 13 30 4 14: 14 50 4 15: 15 40 4

如果确实需要,则可以将NAs替换为0

代码语言:javascript
复制
setDT(sample)[, number := as.integer(factor(rleid(speed > 0 ) * (speed > 0), exclude = 0))][
  is.na(number), number := 0][]

有另一种方法

代码语言:javascript
复制
setDT(sample)[, number := {
  tmp <- speed > 0
  cumsum(tmp  - shift(tmp, fill = 0, type = "lag") > 0) * tmp
}][]

id speed number 1: 1 50 1 2: 2 0 0 3: 3 0 0 4: 4 30 2 5: 5 50 2 6: 6 40 2 7: 7 0 0 8: 8 0 0 9: 9 25 3 10: 10 30 3 11: 11 50 3 12: 12 0 0 13: 13 30 4 14: 14 50 4 15: 15 40 4

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45537141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档