data.frame列中至少连续五年的子集

and*_*har 5 r dataframe data.table

我在R中有一个data.frame/data.table,如下所示:

df <- data.frame(
ID=c(rep("A", 20)),
year=c(1968, 1971, 1972, 1973, 1974, 1976, 1978, 1980, 1982, 1984, 1985, 
       1986, 1987, 1988, 1990, 1991, 1992, 1993, 1994, 1995))
Run Code Online (Sandbox Code Playgroud)

我想将df分配,以便仅保留连续至少五年的条目.在这个例子中,这是两个时期的情况(1984:1988和1990:1995).我怎么能在R中这样做?谢谢你的支持.

Jaa*_*aap 10

使用diff和的紧凑解决方案cumsum:

setDT(df)[, grp := cumsum(c(0, diff(year)) > 1), by = ID
          ][, if (.N > 4) .SD, by = grp][, grp := NULL][]
Run Code Online (Sandbox Code Playgroud)

这给出了期望的结果:

    ID year
 1:  A 1984
 2:  A 1985
 3:  A 1986
 4:  A 1987
 5:  A 1988
 6:  A 1990
 7:  A 1991
 8:  A 1992
 9:  A 1993
10:  A 1994
11:  A 1995
Run Code Online (Sandbox Code Playgroud)

说明:

  • 随着grp := cumsum(c(0, diff(year)) > 1), by = ID你为每个创建一个(临时)分组变量连续几年ID.
  • 随着if (.N > 4) .SD, by = grp您选择具有连续5年以上的唯一群体.
  • 随着grp := NULL你删除(临时)分组变量.

基数为R的比较方法:

i <- with(df, ave(year, ID, FUN = function(x) { 
  r <- rle(cumsum(c(0, diff(year)) > 1));
  rep(r$lengths, r$lengths)
  } ))

df[i > 4,] # or df[which(i > 4),]
Run Code Online (Sandbox Code Playgroud)

这会得到相同的结果.


小智 6

这是另一种方式:

df2 <- NULL 
   sapply(seq(nrow(df)), function(x)
             {
              ifelse((sum(diff(df[x:(x+4), "year"], 1)) == 4 &
                      sum(diff(df[x:(x+4), "year"], 1) == 1) == 4),
                      df2 <<- rbind(df2, df[x:(x+4),]),"")
             })
df2 <- unique(df2)
Run Code Online (Sandbox Code Playgroud)