删除特定年份范围内的行,而不使用R中的for循环

问题描述 投票:0回答:3

我正在寻找一种方法来省略不在两个特定值之间的行,而不使用for循环。年份列中的所有行都在1999年到2002年之间,但是其中一些行不包括这两个日期之间的所有年份。您可以看到如下初始数据:

a <- data.frame(year = c(2000:2002,1999:2002,1999:2002,1999:2001), 
                id=c(4,6,2,1,3,5,7,4,2,0,-1,-3,4,3))

   year id
1  2000  4
2  2001  6
3  2002  2
4  1999  1
5  2000  3
6  2001  5
7  2002  7
8  1999  4
9  2000  2
10 2001  0
11 2002 -1
12 1999 -3
13 2000  4
14 2001  3

已处理的数据集应仅包含1999:2002之间的连续行。以下data.frame正是我需要的:

  year id
1 1999  1
2 2000  3
3 2001  5
4 2002  7
5 1999  4
6 2000  2
7 2001  0
8 2002 -1

当我执行以下for循环时,我得到以前的data.frame没有任何问题:

for(i in 1:which(a$year == 2002)[length(which(a$year == 2002))]){
  if(a[i,1] == 1999 & a[i+3,1] == 2002){
    b <- a[i:(i+3),]
  }else{next}

  if(!exists("d")){
    d <- b
  }else{
    d <- rbind(d,b)
  }
}

但是,我有超过100万行,我需要在不使用for循环的情况下完成此过程。那有更快的方法吗?

r for-loop dataframe grouping
3个回答
0
投票

你可以试试这个。首先我们创建连续数字组,然后我们加入完整的日期范围,然后我们过滤任何组是否已满。如果您已经有一个分组变量,这可以减少很多。

library(tidyverse)

df <- data_frame(year = c(2000:2002,1999:2002,1999:2002,1999:2001), 
                id=c(4,6,2,1,3,5,7,4,2,0,-1,-3,4,3))

df %>% 
  mutate(groups = cumsum(c(0,diff(year)!=1))) %>% 
  nest(-groups) %>%
  mutate(data = map(data, .f = ~full_join(.x, data_frame(year = 1999:2002), by = "year")),
         drop = map_lgl(data, ~any(is.na(.x$id)))) %>%
  filter(drop == FALSE) %>% 
  unnest() %>%
  select(-c(groups, drop))
#> # A tibble: 8 x 2
#>    year    id
#>   <int> <dbl>
#> 1  1999     1
#> 2  2000     3
#> 3  2001     5
#> 4  2002     7
#> 5  1999     4
#> 6  2000     2
#> 7  2001     0
#> 8  2002    -1

reprex package创建于2018-08-31(v0.2.0)。


0
投票

有一个功能可以自动执行此操作。

首先,使用命令dplyrtidyverse安装名为install.packages("dplyr")install.packages("tidyverse")的软件包。

然后,使用library(dplyr)加载包。

然后,使用filter函数:a_filtered = filter(a, year >=1999 & year < 2002)

即使有很多行,这应该很快。


0
投票

我们也可以通过基于检查'年'1999的逻辑表达式创建分组列,然后通过将filter'年'检查为'1999',将first检查为'2002'并将last if检查为'年'来创建分组列。出现在特定的'grp'

all
© www.soinside.com 2019 - 2024. All rights reserved.