How to use mutate in a for loop that dynamically calculates column names and changes dates to compare?

Viewed 70

I am trying to take a date range and then determine whether the status is New, InProcess, or Ordered (complete) for each day in the date range. I have a start date and end date, and then get the days between. Then, I want to create a column for each day in the date range with the status for that day. So, both the column name and the case_when statements are dynamic based on the date range. The code below generates the three columns correctly, but doesn't fill them in except for the first. Is there a way to do this using purrr? Or is a loop the best way to go? How do I get it to calculate correctly over all columns?

start_date <- as.Date('2018-10-04')

end_date <- as.Date('2018-10-06')

date_range <- as.list(seq.Date(start_date, end_date, by = "day"))

for (i in seq_along(length(date_range))) {


 test2 <- orderInfo %>% 
  mutate(!!paste0("day", i-1) := case_when(CompleteDate == as.Date(start_date + i-1) ~  "ORDERED",  
                             CreateDate == as.Date(start_date + i-1) ~ "NEW",
                             CreateDate < as.Date(start_date + i-1) & (is.na(CompleteDate) | CompleteDate > as.Date(start_date + i-1)) ~ "InProcess")) 
 
view(test2)

}

When I changed to 1:seq_along(date_range), I got an error that said the only the first number was used.

> for (i in 1:seq_along(date_range)) {
+ 
+ 
+ #orderInfo[ , paste0("day", i-1)]   <- NA
+ 
+ 
+  test2 <- orderInfo %>% 
+   mutate(!!paste0("day", i-1) := case_when(CompleteDate == (as.Date(start_date + i-1)) ~  "ORDERED",  
+                              CreateDate == as.Date(start_date + i-1) ~ "NEW",
+                              CreateDate < as.Date(start_date + i-1) & (is.na(CompleteDate) | CompleteDate > as.Date(start_date + i-1)) ~ "InProcess")) 
+ view(test2)
+ 
+ }
Error : numerical expression has 3 elements: only the first used

Any help is appreciated!!

1 Answers

There are couple of things we could change

  1. Use seq_along(date_range) and loop over it
  2. Initialize 'test2' as the original data ('orderInfo') and update by assignment in each iteration so that new columns will be added in that object. In the OP's code, the 'test2' was getting replaced in each iteration
library(dplyr)
test2 <- orderInfo
for (i in seq_along(date_range)) {


 test2 <- test2 %>% 
    mutate(!!paste0("day", i-1) := case_when(CompleteDate == as.Date(start_date + i-1) ~  "ORDERED",  
                             CreateDate == as.Date(start_date + i-1) ~ "NEW",
                             CreateDate < as.Date(start_date + i-1) & (is.na(CompleteDate) | CompleteDate > as.Date(start_date + i-1)) ~ "InProcess"))  


}
Related