首页 > 解决方案 > 根据多个条件在数据框中插入行

问题描述

我有很多组的大型数据框,可能如下所示:

id       tnr     tnr_grp     tnr_a     tnr_b
150001   1       0           1         0
150001   2       0           2         0
150001   3       0           3         0
150001   4       1           4         0
150001   4-5     1           4         5
150001   6       0           6         0
150001   7       0           7         0
150001   19      0           19        0
150001   20      1           20        0
150001   20-21   1           20        21
150001   22      1           22        0
150001   22-23   1           22        23
150001   24      1           24        0
150001   25      0           25        0

我已经确定了重叠的数字tnr_grp,1表示重叠,0表示不重叠。我还将两个零件号分成tnr_atnr_b。接下来,我需要处理 0 和 1 中的出现tnr_grp。我遇到的问题是我有时有两个重叠的组,但实际上它们不是同一个组。如示例中,20 与 20-21 重叠,22 与 22-23 重叠。我想在这两个组之间插入一个新行,其中id保留tnr_grp为 0,所有其他值为 NA。所以想要的输出应该是这样的:

id       tnr     tnr_grp     tnr_a     tnr_b
150001   1       0           1         0
150001   2       0           2         0
150001   3       0           3         0
150001   4       1           4         0
150001   4-5     1           4         5
150001   6       0           6         0
150001   7       0           7         0
150001   19      0           19        0
150001   20      1           20        0
150001   20-21   1           20        21
150001   NA      0           NA        NA
150001   22      1           22        0
150001   22-23   1           22        23
150001   24      1           24        0
150001   25      0           25        0

因此,我需要一些代码在两行之间插入一行,当tnr_grp为 1tnr_a且不相同时,最好使用 dplyr。我尝试了一些东西,但没有任何东西真正导致某个地方。

重现示例数据的代码:

df <- structure(list(id = c(150001L, 150001L, 150001L, 150001L, 150001L, 
                        150001L, 150001L, 150001L, 150001L, 150001L, 150001L, 150001L, 
                        150001L, 150001L), tnr = c("1", "2", "3", "4", "4-5", "6", "7", 
                                                   "19", "20", "20-21", "22", "22-23", "24", "25"), tnr_grp = c(0L, 
                                                                                                                0L, 0L, 1L, 1L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 0L, 0L), tnr_a = c(1L, 
                                                                                                                                                                               2L, 3L, 4L, 4L, 6L, 7L, 19L, 20L, 20L, 22L, 22L, 24L, 25L), tnr_b = c(0L, 
                                                                                                                                                                                                                                                     0L, 0L, 0L, 5L, 0L, 0L, 0L, 0L, 21L, 0L, 23L, 0L, 0L)), class = "data.frame", row.names = c(NA, 
                                                                                                                                                                                                                                                                                                                                                 -14L))

任何帮助表示赞赏,谢谢!

标签: rdplyr

解决方案


我花了一段时间才明白你的意思——我希望我现在明白了。但我花了更长的时间才决定发布我所拥有的。因为我认为这不是最优雅的解决方案。

但它至少是一个,由于没有其他人,我决定发布它。

library(dplyr)

nam <- colnames(df)

res <- df %>% 
  mutate(rn = row_number()) %>%                         # row numbers
  group_by(tnr_a) %>%  
  mutate(l = n()) %>%                                   # count per group
  mutate(check = ifelse(l == lag(l),T, F)) %>%          # intermediate 
  na.omit() %>% 
  ungroup() %>% 
  mutate(check2 = rn + l) %>%                           # intermediate
  mutate(check3 = ifelse(check2 == lead(rn), T, F)) %>% # intermediate
  filter(!is.na(check3) & check3 == T) %>%              # final filter
  select(all_of(nam)) %>%                               # select right col
  mutate(tnr = NA, tnr_grp = NA, tnr_b = NA)            # get row and mutate to NA where needed

res
#> # A tibble: 1 x 5
#>       id tnr   tnr_grp tnr_a tnr_b
#>    <int> <lgl> <lgl>   <int> <lgl>
#> 1 150001 NA    NA         20 NA

# bind to original DF
df %>% bind_rows(res) %>%                 
  arrange(tnr_a)
#>        id   tnr tnr_grp tnr_a tnr_b
#> 1  150001     1       0     1     0
#> 2  150001     2       0     2     0
#> 3  150001     3       0     3     0
#> 4  150001     4       1     4     0
#> 5  150001   4-5       1     4     5
#> 6  150001     6       0     6     0
#> 7  150001     7       0     7     0
#> 8  150001    19       0    19     0
#> 9  150001    20       1    20     0
#> 10 150001 20-21       1    20    21
#> 11 150001  <NA>      NA    20    NA
#> 12 150001    22       1    22     0
#> 13 150001 22-23       1    22    23
#> 14 150001    24       0    24     0
#> 15 150001    25       0    25     0

推荐阅读