Using a circular list in R to calculate days in a delivery period

59 Views Asked by At

Creating a circular list in R

I am working with a delivery schedule where I need to calculate the days in each unique delivery period. I was trying to solve my related issue in excel originally, but am now thinking I need to use R instead.

If I have list of the days of the week:

DaysOfWeek <- list("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday")

I always want to be able to reference the list and calculate days forward.

For example, if the delivery schedule is Delivery period 1: Friday-Monday, and period 2: is Tuesday-Thursday. I want to be able to reference my list say delivery day 1 is Friday, count forward until the next delivery day, Tuesday, and see that there are four delivery days in that period.

I have tried hard coding specific dates and setting them to the days of the week as well as several different for loops and am still struggling.

3

There are 3 best solutions below

0
deschen On

You could do:

DaysOfWeek <- c("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday")

delivery_start <- 'Sunday'
delivery_end <- 'Tuesday'

delivery_days <- ifelse(which(DaysOfWeek == delivery_start) > which(DaysOfWeek == delivery_end),
                        7 + which(DaysOfWeek == delivery_end) - which(DaysOfWeek == delivery_start),
                        which(DaysOfWeek == delivery_end) - which(DaysOfWeek == delivery_start))

This example would return the result 2.

3
Gregor Thomas On

If I understand what you want, we can use modular arithmetic.

I would code the days of the week as a named vector starting at 0 and then use a little helper function to calculate the differences mod 7.

days = c(
  Monday = 0,
  Tuesday = 1,
  Wednesday = 2,
  Thursday = 3,
  Friday = 4,
  Saturday = 5,
  Sunday = 6
)

day_diff = function(from, to) {
  unname((days[to] - days[from]) %% 7)
}

day_diff("Friday", "Tuesday")
# [1] 4 

day_diff("Saturday", "Sunday")
# [1] 1

day_diff("Sunday", "Saturday")
# [1]  6 
0
LMc On

Here is a possibility where you double your days of the week vector and then find the shortest positive distance between two days:

DayofWeek <- rep(c("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"), 2)

days_between <- function(day1, day2) {
  start <- which(DayofWeek == day1)
  end <- which(DayofWeek == day2)
  
  min(Filter(\(x) x > 0, sapply(end, `-`, start)))
}

Output

days_between("Monday", "Saturday")
[1] 5
days_between("Sunday", "Monday")
[1] 1