r语言 - Group_by id 并计算相切的 NA,然后在遇到新的 NA 系列时重新开始计数



我有一个这样的数据帧:

df <- data_frame(id = c(rep('A', 10), rep('B', 10)),
value = c(1:3, rep(NA, 2), 1:2, rep(NA, 3), 1, rep(NA, 4), 1:3, rep(NA, 2)))

我需要计算value列中连续NA的数量。计数需要按ID分组,每次遇到新的NA或新的NA系列时,计数都需要在1处重新启动。检测到的输出应该是这样的:

df$expected_output <- c(rep(NA, 3), 1:2, rep(NA, 2), 1:3, NA, 1:4, rep(NA, 3), 1:2)

如果有人能给我一个dplyr解决方案,那也很棒:(

我试过一些方法,但都没有得到任何有意义的结果。提前感谢^!

使用dplyrdata.table的解决方案。

library(dplyr)
library(data.table)
df2 <- df %>%
group_by(id) %>%
mutate(info = rleid(value)) %>%
group_by(id, info) %>%
mutate(expected_output = row_number()) %>%
ungroup() %>%
mutate(expected_output = ifelse(!is.na(value), NA, expected_output)) %>%
select(-info)
df2
# # A tibble: 20 x 3  
#     id    value expected_output
#     <chr> <dbl>           <int>
#  1 A         1              NA
#  2 A         2              NA
#  3 A         3              NA
#  4 A        NA               1
#  5 A        NA               2
#  6 A         1              NA
#  7 A         2              NA
#  8 A        NA               1
#  9 A        NA               2
# 10 A        NA               3
# 11 B         1              NA
# 12 B        NA               1
# 13 B        NA               2
# 14 B        NA               3
# 15 B        NA               4
# 16 B         1              NA
# 17 B         2              NA
# 18 B         3              NA
# 19 B        NA               1
# 20 B        NA               2

我们可以使用rle来获取是或不是na的组的长度,如果它们是NA,则使用purrr::map2来应用seq,并使用rep来获取增长计数或仅填充NA值。

library(tidyverse)
count_na <- function(x) {
r <- rle(is.na(x))
consec <- map2(r$lengths, r$values, ~ if (.y) seq(.x) else rep(NA, .x))
unlist(consec)
}
df %>%
mutate(expected_output = count_na(value))
#> # A tibble: 20 × 3
#>    id    value expected_output
#>    <chr> <dbl>           <int>
#>  1 A         1              NA
#>  2 A         2              NA
#>  3 A         3              NA
#>  4 A        NA               1
#>  5 A        NA               2
#>  6 A         1              NA
#>  7 A         2              NA
#>  8 A        NA               1
#>  9 A        NA               2
#> 10 A        NA               3
#> 11 B         1              NA
#> 12 B        NA               1
#> 13 B        NA               2
#> 14 B        NA               3
#> 15 B        NA               4
#> 16 B         1              NA
#> 17 B         2              NA
#> 18 B         3              NA
#> 19 B        NA               1
#> 20 B        NA               2

以下是使用rle:的解决方案

x <- rle(is.na(df$value))
df$new[is.na(df$value)] <- sequence(x$lengths[x$values])
# A tibble: 20 x 3
id    value   new
<chr> <dbl> <int>
1 A         1    NA
2 A         2    NA
3 A         3    NA
4 A        NA     1
5 A        NA     2
6 A         1    NA
7 A         2    NA
8 A        NA     1
9 A        NA     2
10 A        NA     3
11 B         1    NA
12 B        NA     1
13 B        NA     2
14 B        NA     3
15 B        NA     4
16 B         1    NA
17 B         2    NA
18 B         3    NA
19 B        NA     1
20 B        NA     2

另一个解决方案:

library(tidyverse)
df %>% 
mutate(aux =data.table::rleid(value)) %>% 
group_by(id, aux) %>% 
mutate(eout = ifelse(is.na(value), row_number(), NA_real_)) %>%
ungroup %>% select(-aux)
#> # A tibble: 20 × 4
#>    id    value expected_output  eout
#>    <chr> <dbl>           <int> <dbl>
#>  1 A         1              NA    NA
#>  2 A         2              NA    NA
#>  3 A         3              NA    NA
#>  4 A        NA               1     1
#>  5 A        NA               2     2
#>  6 A         1              NA    NA
#>  7 A         2              NA    NA
#>  8 A        NA               1     1
#>  9 A        NA               2     2
#> 10 A        NA               3     3
#> 11 B         1              NA    NA
#> 12 B        NA               1     1
#> 13 B        NA               2     2
#> 14 B        NA               3     3
#> 15 B        NA               4     4
#> 16 B         1              NA    NA
#> 17 B         2              NA    NA
#> 18 B         3              NA    NA
#> 19 B        NA               1     1
#> 20 B        NA               2     2

最新更新