Search code examples
rdplyrnested-loopsdata-manipulationstringr

How to make a loop that changes values in specific rows from a dictionary


I'm new and can't figure it out how to solve this problem. I have a data.frame = schedule

Week_number Start End
1 09:00 15:00
1 09:00 15:00
1 09:00 15:00
1 09:00 15:00
1 09:00 15:00
1 NA NA
1 NA NA
2 09:00 15:00
2 09:00 15:00
2 09:00 15:00
2 09:00 15:00
2 09:00 15:00
2 NA NA
2 NA NA
3 09:00 15:00
3 09:00 15:00
3 09:00 15:00
3 09:00 15:00
3 09:00 15:00
3 NA NA
3 NA NA
-----------------------------
..
52
-----------------------------

I have a shift dictionary :

> start_vec <- c("06:00", "08:00", "14:00")
> end_vec <- c("14:00", "16:00", "22:00")

My loop is to go through all 52 weeks and replace 9am and 3pm with a dictionary value. But the problem is that the values should not be repeated, i.e. each week should be different.

For example, I start the year with : 08:00 - 16:00. The year can start with any shift. Please find an example below :

Week_number Start End
1 08:00 16:00
1 08:00 16:00
1 08:00 16:00
1 08:00 16:00
1 08:00 16:00
1 NA NA
1 NA NA
2 14:00 22:00
2 14:00 22:00
2 14:00 22:00
2 14:00 22:00
2 14:00 22:00
2 NA NA
2 NA NA
3 06:00 14:00
3 06:00 14:00
3 06:00 14:00
3 06:00 14:00
3 06:00 14:00
3 NA NA
3 NA NA
-----------------------------
..
52
-----------------------------

I tryed to make nest loop, or make week_number vector to be able replace all 1 without NA with specific value.

> rd_dt <- data.frame()
> for (i in 1:length(schedule$Week_number)){
> for (s in start_vec){
> for (e in end_vec){
> dt <- schedule[i,] 
> if (schedule$Start == NA){
> next
> else {

Thanks in advance for any hint.


Solution

  • I think you do not need a loop to do this. Here is one approach that may be helpful. Using ifelse check for NA - if not NA, then refer to start_vec and end_vec for substitute values. It will use the Week_number as an index in your vector, and uses the %% modulus operator where 3 is the length of your vectors, so it will restart at beginning if exceeds the length of the vectors.

    library(dplyr)
    
    df %>%
      mutate(Start = ifelse(is.na(Start), NA, start_vec[1 + Week_number %% 3]),
             End = ifelse(is.na(End), NA, end_vec[1 + Week_number %% 3]))
    

    Output

       Week_number Start   End
    1            1 08:00 16:00
    2            1 08:00 16:00
    3            1 08:00 16:00
    4            1 08:00 16:00
    5            1 08:00 16:00
    6            1  <NA>  <NA>
    7            1  <NA>  <NA>
    8            2 14:00 22:00
    9            2 14:00 22:00
    10           2 14:00 22:00
    11           2 14:00 22:00
    12           2 14:00 22:00
    13           2  <NA>  <NA>
    14           2  <NA>  <NA>
    15           3 06:00 14:00
    16           3 06:00 14:00
    17           3 06:00 14:00
    18           3 06:00 14:00
    19           3 06:00 14:00
    20           3  <NA>  <NA>
    21           3  <NA>  <NA>