#r #datetime #dplyr #lubridate
Вопрос:
Попытка сгенерировать последовательность дат в программировании R (с использованием lubridate) дат с заданной датой начала и частотой-это не числовое значение, а дни, в которые могут произойти даты.
Ниже приведена таблица, в которой определены группа, дата начала, день и флаг события
------- ------------ ----- -----
| Group | start_date | Day | Y/N |
------- ------------ ----- -----
| foo | 02-06-2021 | Mon | 0 |
| foo | 02-06-2021 | Tue | 1 |
| foo | 02-06-2021 | Wed | 0 |
| foo | 02-06-2021 | Thu | 1 |
| foo | 02-06-2021 | Fri | 1 |
| foo | 02-06-2021 | Sat | 1 |
| foo | 02-06-2021 | Sun | 0 |
| bar | 02-06-2021 | Mon | 1 |
| bar | 02-06-2021 | Tue | 0 |
| bar | 02-06-2021 | Wed | 0 |
| bar | 02-06-2021 | Thu | 1 |
| bar | 02-06-2021 | Fri | 1 |
| bar | 02-06-2021 | Sat | 0 |
| bar | 02-06-2021 | Sun | 0 |
------- ------------ ----- -----
Требуемая производительность, как показано ниже.
------- ------------ ---------------------
| Group | given_date | next_available_date |
------- ------------ ---------------------
| foo | 02-06-2021 | 03-06-2021 |
| foo | 04-06-2021 | 04-06-2021 |
| foo | 06-06-2021 | 08-06-2021 |
| bar | 02-06-2021 | 03-06-2021 |
| bar | 05-06-2021 | 07-06-2021 |
------- ------------ ---------------------
Некоторые идеи вокруг цикла while, которые, как я думал, могут быть утомительными.
for each given_date{
inputdate = given_date
while(true){
{
if(group =="Foo" amp; day(inputdate) in ('Tue','Thu','Fri','Sat')
next_available_date=inputdate
break
}
else
{
inputdate = inputdate (1 day) (repeat the loop until if condition is satisfied)
}
}
}
Если условия для разных групп могут быть разными.
Не в состоянии понять, как использовать неравномерную частоту, чтобы получить следующую доступную дату.
Комментарии:
1. Можете ли вы объяснить результат? Что же
Day
представляет собой? Что такоеY/N
? Также, как вы вычисляетеgiven_date
иnext_available_date
?2. Y/N-это основа флага, на которой мы определим, может ли произойти дата или нет, например : для foo и заданной даты 02-06-2021, которая является средой, следующая доступная дата не может быть ср, потому что столбец Y/N имеет 0 против Ср, следующая доступная дата тогда будет 03-06-2021, что Чт и Y/N = 1, тот же случай будет применяться для бара 05-06-2021, который сб, но с флага Y/N и сб и вс 0,0 соответственно, следовательно, следующая доступная дата будет приходиться на 07-06-2021
3. Извините, если я не совсем ясно выражаюсь, новичок в stackoverflow
4. Да дата начала останется прежней для группы
5. Конечно, сделаю это
Ответ №1:
Работа над более крупной выборкой, как обсуждалось ранее в комментариях. Последовала стратегия —
- Поскольку ваш
day
столбец всегда начинается сMon
того, что не равноstart_date
, поэтому требуется сопоставление столбцовweekday
. - Таким образом, создано
day
поле упорядоченногоfactor
типа, чтобы им можно было манипулировать, превращая его в целые числа. - Расположите фрейм данных таким образом, чтобы каждая ваша группа начиналась только с этого дня. Для этого используется деление
%%
по модулю - После организации задача стала несколько проще. Я создал семь дат для каждого конца рабочего дня, для каждой группы и для каждой даты начала.
- Отфильтрованные строки с
Y/N
0 в любом месте. - Теперь вам требуется только верхний ряд, поэтому используется
slice_head()
df <- data.frame(
stringsAsFactors = FALSE,
Group = c("foo","foo","foo",
"foo","foo","foo","foo","foo","foo","foo",
"foo","foo","foo","foo","foo","foo","foo",
"foo","foo","foo","foo","bar","bar","bar",
"bar","bar","bar","bar","bar","bar","bar","bar",
"bar","bar","bar"),
start_date = c("02-06-2021",
"02-06-2021","02-06-2021","02-06-2021","02-06-2021",
"02-06-2021","02-06-2021","04-06-2021",
"04-06-2021","04-06-2021","04-06-2021","04-06-2021",
"04-06-2021","04-06-2021","06-06-2021","06-06-2021",
"06-06-2021","06-06-2021","06-06-2021",
"06-06-2021","06-06-2021","02-06-2021","02-06-2021",
"02-06-2021","02-06-2021","02-06-2021","02-06-2021",
"02-06-2021","05-06-2021","05-06-2021",
"05-06-2021","05-06-2021","05-06-2021","05-06-2021",
"05-06-2021"),
Day = c("Mon","Tue","Wed",
"Thu","Fri","Sat","Sun","Mon","Tue","Wed",
"Thu","Fri","Sat","Sun","Mon","Tue","Wed",
"Thu","Fri","Sat","Sun","Mon","Tue","Wed",
"Thu","Fri","Sat","Sun","Mon","Tue","Wed","Thu",
"Fri","Sat","Sun"),
y_n = c(0L,1L,0L,1L,1L,
1L,0L,0L,1L,0L,1L,1L,1L,0L,0L,1L,0L,1L,
1L,1L,0L,1L,0L,0L,1L,1L,0L,0L,1L,0L,
0L,1L,1L,0L,0L)
)
library(lubridate)
library(tidyverse)
df %>% group_by(Group, start_date) %>%
mutate(Day = factor(Day, levels = Day, ordered = T)) %>%
arrange(Group, (as.numeric(Day) 7 - wday(dmy(start_date), week_start = 1)) %% 7, .by_group = T) %>%
mutate(next_available_date = dmy(start_date) 0:6) %>%
filter(y_n !=0) %>%
slice_head()
#> # A tibble: 5 x 5
#> # Groups: Group, start_date [5]
#> Group start_date Day y_n next_available_date
#> <chr> <chr> <ord> <int> <date>
#> 1 bar 02-06-2021 Thu 1 2021-06-03
#> 2 bar 05-06-2021 Mon 1 2021-06-07
#> 3 foo 02-06-2021 Thu 1 2021-06-03
#> 4 foo 04-06-2021 Fri 1 2021-06-04
#> 5 foo 06-06-2021 Tue 1 2021-06-08
На основании предоставленных данных
df <- data.frame(
stringsAsFactors = FALSE,
Group = c("foo","foo","foo",
"foo","foo","foo","foo","bar","bar","bar",
"bar","bar","bar","bar"),
start_date = c("02-06-2021",
"02-06-2021","02-06-2021","02-06-2021","02-06-2021",
"02-06-2021","02-06-2021","02-06-2021",
"02-06-2021","02-06-2021","02-06-2021","02-06-2021",
"02-06-2021","02-06-2021"),
Day = c("Mon","Tue","Wed",
"Thu","Fri","Sat","Sun","Mon","Tue","Wed",
"Thu","Fri","Sat","Sun"),
y_n = c(0L,1L,0L,1L,1L,
1L,0L,1L,0L,0L,1L,1L,0L,0L)
)
library(lubridate)
library(tidyverse)
df %>% group_by(Group, start_date) %>%
mutate(Day = factor(Day, levels = Day, ordered = T)) %>%
arrange(Group, (as.numeric(Day) 7 - wday(dmy(start_date), week_start = 1)) %% 7, .by_group = T) %>%
mutate(next_available_date = dmy(start_date) 0:6) %>%
filter(y_n !=0) %>%
slice_head()
#> # A tibble: 2 x 5
#> # Groups: Group, start_date [2]
#> Group start_date Day y_n next_available_date
#> <chr> <chr> <ord> <int> <date>
#> 1 bar 02-06-2021 Thu 1 2021-06-03
#> 2 foo 02-06-2021 Thu 1 2021-06-03
Создано 2021-06-02 пакетом reprex (v2.0.0)
Комментарии:
1. Не уверен, как работает код, если вы дадите краткое объяснение, я изучу его дальше