Подход tidyverse
будет заключаться в преобразовании кадра данных в длинный формат, чтобы теперь у нас было две строки для каждой строки в исходном кадре данных. Теперь для каждой строки мы используем match
, чтобы получить индекс значения месяца в начале и конце месяца, а затем используем его, чтобы создать последовательность.
library(tidyverse)
df %>%
gather(key, Month, -(1:3)) %>%
group_by_at(1:3) %>%
complete(Month = month.abb[match(Month[1], month.abb):
match(Month[2], month.abb)]) %>%
arrange(Customer, Product, Price, match(Month, month.abb)) %>%
select(-key)
# Customer Product Price Month
# <fct> <fct> <int> <chr>
# 1 ABC XYZ 100 Jan
# 2 ABC XYZ 100 Feb
# 3 ABC XYZ 100 Mar
# 4 ABC XYZ 100 Apr
# 5 ABC XYZ 100 May
# 6 ABC XYZ 100 Jun
# 7 ABC XYZ 150 Jul
# 8 ABC XYZ 150 Aug
# 9 ABC XYZ 150 Sep
#10 ABC XYZ 150 Oct
#11 ABC XYZ 150 Nov
#12 ABC XYZ 150 Dec
Или другой вариант, используя map2
df %>%
mutate(Month = map2(Start_Month, End_Month,
~month.abb[match(.x, month.abb) : match(.y, month.abb)])) %>%
unnest() %>%
select(-Start_Month, -End_Month)
который в базе R будет использовать Map
do.call(rbind, Map(function(x, y, z) cbind(df[z,],
Month = month.abb[match(x, month.abb) : match(y, month.abb)]),
df$Start_Month, df$End_Month, seq_len(nrow(df))))
Здесь мы используем встроенный вектор month.abb
, чтобы получить последовательность
month.abb
# [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"