如何根据连续序列过滤满足条件的行?

时间:2019-07-25 11:38:21

标签: r dataframe dplyr

我希望在数据框中的行被子集化,条件是特定的值序列出现在一行中。例如,如果在变量之一中存在模式2 | 4 | 5一个接一个的行,将保留这三行,然后继续搜索,直到找到另一行并找到另外2行。 4 | 5.最终,我想每2个组中使用group_by()。 4 | 5,并在另一列中取相应值的平均值。

我尝试使用各种滞后命令,但无法使其正常工作。理想情况下,解决方案是使用dplyr。

给出下表

# A tibble: 24 x 2
   information.content scale_degree
                 <dbl>        <dbl>
 1               4.95             0
 2               2.98             2
 3               2.13             4
 4               2.46             2
 5               2.49             4
 6               1.75             5
 7               1.95             7
 8               2.54             5
 9               0.969            4
10               1.45             2
11               2.10             4
12               2.37             2
13               2.07             4
14               1.29             5
15               1.43             7
16               4.05             7
17               2.05             5
18               0.740            4
19               1.07             2
20               1.92             0
21               2.54             2
22               1.72             4
23               1.69             2
24               1.85             0

structure(list(information.content = c(4.951615, 2.9770234, 2.1338997, 
2.4575028, 2.4881902, 1.7465432, 1.9471669, 2.5410578, 0.96890986, 
1.4460193, 2.0989947, 2.3660812, 2.0733728, 1.2867087, 1.4285704, 
4.048128, 2.0472896, 0.74006027, 1.0694636, 1.9193107, 2.5353878, 
1.721423, 1.6873852, 1.8456767), scale_degree = c(0, 2, 4, 2, 
4, 5, 7, 5, 4, 2, 4, 2, 4, 5, 7, 7, 5, 4, 2, 0, 2, 4, 2, 0)), row.names = c(NA, 
-24L), class = c("tbl_df", "tbl", "data.frame"))

我希望得到以下结果(会知道如何在没有问题的情况下进行分组和平均)

# A tibble: 6 x 3
  information.content scale_degree instance
                <dbl>        <dbl>    <dbl>
1                2.46            2        1
2                2.49            4        1
3                1.75            5        1
4                2.37            2        2
5                2.07            4        2
6                1.29            5        2

structure(list(information.content = c(2.4575028, 2.4881902, 
1.7465432, 2.3660812, 2.0733728, 1.2867087), scale_degree = c(2, 
4, 5, 2, 4, 5), instance = c(1, 1, 1, 2, 2, 2)), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -6L), spec = structure(list(
    cols = list(information.content = structure(list(), class = c("collector_double", 
    "collector")), scale_degree = structure(list(), class = c("collector_double", 
    "collector")), instance = structure(list(), class = c("collector_double", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

3 个答案:

答案 0 :(得分:2)

通过dplyr的想法可能是利用lead函数,即

library(dplyr)

df %>% 
 mutate(new = cumsum(ifelse(scale_degree == 2 & 
                            lead(scale_degree, n = 1) == 4 & 
                                lead(scale_degree, n = 2) == 5, 1, 0))) %>% 
 filter(new != 0) %>% 
 group_by(new) %>% 
 slice(1L:3L)

给出,

# A tibble: 6 x 3
# Groups:   new [2]
  information.content scale_degree   new
                <dbl>        <dbl> <dbl>
1                2.46            2     1
2                2.49            4     1
3                1.75            5     1
4                2.37            2     2
5                2.07            4     2
6                1.29            5     2

答案 1 :(得分:2)

另一种dplyr可能是:

df %>%
 mutate(flag = row_number() %in% grepRaw("245", 
                                         paste0(scale_degree, collapse = ""), 
                                         all = TRUE,
                                         fixed = TRUE)) %>%
 group_by(flag = cumsum(flag)) %>%
 filter(flag != 0) %>% 
 slice(1:3)

  information.content scale_degree  flag
                <dbl>        <dbl> <int>
1                2.46            2     1
2                2.49            4     1
3                1.75            5     1
4                2.37            2     2
5                2.07            4     2
6                1.29            5     2

注意:

如果“ scale_degree”的值介于0到9之间,它将起作用。

“ scale_degree”可能具有任何值的可能性:

df %>%
 mutate(flag = row_number() %in% ((grepRaw("2,4,5",
                            paste0(c(0, scale_degree, 0), collapse = ","),
                            all = TRUE,
                            fixed = TRUE) - 1) / 2)) %>%
 group_by(flag = cumsum(flag)) %>%
 filter(flag != 0) %>% 
 slice(1:3) 

答案 2 :(得分:1)

这是使用dplyr软件包的一种可能的解决方案(可能不是最优雅的方法):

library(dplyr)
df %>% 
  filter((scale_degree == 2 & lead(scale_degree) == 4 & lead(scale_degree, 2) == 5) |
           (scale_degree == 4 & lag(scale_degree) == 2 & lead(scale_degree) == 5) |
           (scale_degree == 5 & lag(scale_degree) == 4 & lag(scale_degree, 2) == 2)) %>%
  mutate(instance = cumsum(scale_degree == 2))

    # A tibble: 6 x 3
  information.content scale_degree instance
                <dbl>        <dbl>    <int>
1                2.46            2        1
2                2.49            4        1
3                1.75            5        1
4                2.37            2        2
5                2.07            4        2
6                1.29            5        2