只保留连续观察

时间:2017-10-09 12:31:57

标签: r dataframe

如标题中所述,我有一个如下所示的data.frame,

df<-data.frame('id'=c('1','1','1','1','1','1','1'),'time'=c('1998','2000','2001','2002','2003','2004','2007'))
df
  id time
1  1 1998
2  1 2000
3  1 2001
4  1 2002
5  1 2003
6  1 2004
7  1 2007

还有一些案例的时间窗口比这更短或更长,仅仅是为了说明。

我想对这个数据集做两件事,首先,在这里找到所有至少连续五次观察的id,这可以通过以下解决方案来完成{{3 }}。其次,我想仅保留第一步选择的{strong>至少连续五行 id中的观察结果。理想的结果是:

df
  id time
1  1 2000
2  1 2001
3  1 2002
4  1 2003
5  1 2004

我可以使用for循环和diff函数编写一个复杂的函数,但是如果我有一个更大的数据集(如果id,那么在编写函数和获取结果时这可能非常耗时。 }。但这似乎不像R和我确实应该有一两行解决方案。

任何人都知道如何实现这一目标?你的时间和知识将深受赞赏。提前谢谢。

3 个答案:

答案 0 :(得分:4)

您可以使用dplyr分组id和连续时间,filter组少于5个分组,即

#read data with stringsAsFactors = FALSE
df<-data.frame('id'=c('1','1','1','1','1','1','1'),
               'time'=c('1998','2000','2001','2002','2003','2004','2007'), 
                                                     stringsAsFactors = FALSE)

library(dplyr)

df %>% 
 mutate(time = as.integer(time)) %>% 
 group_by(id, grp = cumsum(c(1, diff(time) != 1))) %>% 
 filter(n() >= 5)

给出了

# A tibble: 5 x 3
# Groups:   id, grp [1]
     id  time   grp
  <chr> <int> <dbl>
1     1  2000     2
2     1  2001     2
3     1  2002     2
4     1  2003     2
5     1  2004     2

答案 1 :(得分:0)

来自dplyrtidyrdata.table的解决方案。

library(dplyr)
library(tidyr)
library(data.table)

df2 <- df %>%
  mutate(time = as.numeric(as.character(time))) %>%
  arrange(id, time) %>%
  right_join(data_frame(time = full_seq(.$time, 1)), by = "time") %>%
  mutate(RunID = rleid(id)) %>%
  group_by(RunID) %>%
  filter(n() >= 5, !is.na(id)) %>%
  ungroup() %>%
  select(-RunID)
df2
# A tibble: 5 x 2
      id  time
  <fctr> <dbl>
1      1  2000
2      1  2001
3      1  2002
4      1  2003
5      1  2004

答案 2 :(得分:0)

与@Sotos答案类似,此解决方案使用seqle(来自cgwtools)作为分组变量:

library(dplyr)
library(cgwtools)

df %>% 
  mutate(time = as.numeric(time)) %>%
  group_by(id, consec = rep(seqle(time)$length, seqle(time)$length)) %>%
  filter(consec >= 5) 

<强>结果:

# A tibble: 5 x 3
# Groups:   id, consec [1]
     id  time consec
  <chr> <dbl>  <int>
1     1  2000      5
2     1  2001      5
3     1  2002      5
4     1  2003      5
5     1  2004      5

删除分组变量:

df %>% 
  mutate(time = as.numeric(time)) %>%
  group_by(id, consec = rep(seqle(time)$length, seqle(time)$length)) %>%
  filter(consec >= 5) %>%
  ungroup() %>%
  select(-consec)

<强>结果:

# A tibble: 5 x 2
     id  time
  <chr> <dbl>
1     1  2000
2     1  2001
3     1  2002
4     1  2003
5     1  2004

数据:

df<-data.frame('id'=c('1','1','1','1','1','1','1'),
               'time'=c('1998','2000','2001','2002','2003','2004','2007'),
               stringsAsFactors = FALSE)