How to generate multiple rows conditioned on the current rows using dplyr in R?

Viewed 48

I have a data frame containing multiple 4 digit codes. Based on the value of the third digit I would like to manipulate the data frame in the following way:

  1. If 3rd digit != "0" do nothing
  2. If 3rd digit == "0" then eliminate this element and replace it with the following one xx{10-99}. Where xx are the initial fist two digits of the element and {10-99} indicates {xx10,xx11,xx12,...,xx99} should be added to the data frame.

Any ideas how this could be implemented maybe with dplyr? Thanks in advance!

e.g.

df <- data.frame("id"= c("1111","1231","1000","2222","2900")
df

and i would like to convert df to the following df

{"1111","1231","1010","1011",...,"1099","2222","2910","2911",..."2999"}
2 Answers
library(dplyr)
dat <- tibble(id = 1:2, code = c("1111", "2201"))
dat
# # A tibble: 2 x 2
#      id code 
#   <int> <chr>
# 1     1 1111 
# 2     2 2201 

dat %>%
  filter(substr(code, 3, 3) == "0") %>%
  rowwise() %>%
  do({
    newcodes <- sprintf("%02i", 0:3)
    mutate(as_tibble(.)[rep(1, length(newcodes)),],
           code = paste0(substr(code, 1, 2), newcodes))
  }) %>%
  bind_rows(filter(dat, substr(code, 3, 3) != "0"), .)
# # A tibble: 5 x 2
#      id code 
#   <int> <chr>
# 1     1 1111 
# 2     2 2200 
# 3     2 2201 
# 4     2 2202 
# 5     2 2203 

I went from 00 to 03, you can fill it out to whatever you want.

One more approach using tidyr::uncount

df <- data.frame("id" = c("1111","1231","1000","2222","2900"))

library(tidyverse)
df %>% uncount(ifelse(substr(id, 3, 3) == '0', 90, 1)) %>%
  group_by(id) %>%
  mutate(id = ifelse(substr(id, 3, 3) == '0', 
                        paste0(substr(id, 1, 2), row_number() + 9), 
                        id)) %>%
  ungroup
#> # A tibble: 183 x 1
#>    id   
#>    <chr>
#>  1 1111 
#>  2 1231 
#>  3 1010 
#>  4 1011 
#>  5 1012 
#>  6 1013 
#>  7 1014 
#>  8 1015 
#>  9 1016 
#> 10 1017 
#> # ... with 173 more rows

Created on 2021-05-28 by the reprex package (v2.0.0)

Related