Insert increment sequence of numbers between two numbers

Problem: How to insert increment sequence of numbers by 30 between two numbers for each unique Patient ID.

I have 1000+ patient id in real data sets. Tidyverse solution would be awesome help.

Thank you

Sample data

library (tidyverse)

sample_data <- tibble::tribble(
  ~Patient_ID, ~min, ~max,
       "ID_1",  -90,  270,
       "ID_2",  -60,  180)

I am expecting to have a sequence of numbers incremental by 30 for each patient ID.

Expected output

expected_output <- tibble::tribble(
                     ~Patient_ID, ~Numbers,
                          "ID_1",      -90,
                          "ID_1",      -60,
                          "ID_1",      -30,
                          "ID_1",        0,
                          "ID_1",       30,
                          "ID_1",       60,
                          "ID_1",       90,
                          "ID_1",      120,
                          "ID_1",      150,
                          "ID_1",      180,
                          "ID_1",      210,
                          "ID_1",      240,
                          "ID_1",      270,
                          "ID_2",      -60,
                          "ID_2",      -30,
                          "ID_2",        0,
                          "ID_2",       30,
                          "ID_2",       60,
                          "ID_2",       90,
                          "ID_2",      120,
                          "ID_2",      150,
                          "ID_2",      180
                     )

My attempt which doesn't work

sample_data %>% 
  group_by(Patient_ID) %>% 
  mutate(Seq = seq(min, max, by = 30))
1 Like

Something like that?

library (tidyverse)

sample_data <- tibble::tribble(
  ~Patient_ID, ~min, ~max,
  "ID_1",  -90,  270,
  "ID_2",  -60,  180)

expected_output <- tibble::tribble(
  ~Patient_ID, ~Numbers,
  "ID_1",      -90,
  "ID_1",      -60,
  "ID_1",      -30,
  "ID_1",        0,
  "ID_1",       30,
  "ID_1",       60,
  "ID_1",       90,
  "ID_1",      120,
  "ID_1",      150,
  "ID_1",      180,
  "ID_1",      210,
  "ID_1",      240,
  "ID_1",      270,
  "ID_2",      -60,
  "ID_2",      -30,
  "ID_2",        0,
  "ID_2",       30,
  "ID_2",       60,
  "ID_2",       90,
  "ID_2",      120,
  "ID_2",      150,
  "ID_2",      180
)

output <- sample_data %>% 
  dplyr::mutate(Numbers = purrr::map2(min, max, ~seq(.x, .y, by = 30))) %>% 
  tidyr::unnest(Numbers) %>%
  dplyr::select(-min, -max)

dplyr::all_equal(expected_output, output)
#> [1] TRUE

Created on 2019-09-10 by the reprex package (v0.3.0)

8 Likes

@mishabalyasin that was so quick and just the right solution I needed. Thank you so much. This will so much help my work project.

I've always neglected vector looping. I think its high time I learn purrr.

2 Likes

Here's another option that avoids map but requires a group_by:

library(tidyverse)

sample_data %>% 
  group_by(Patient_ID) %>% 
  mutate(Numbers=list(seq(min, max, 30))) %>% 
  unnest %>% 
  select(-min, -max)
5 Likes

Hey @joels that is great solution. I really like its simplicity. Thank you