R: Finding out between which dates a certain action occurs
I am working with the R programming language.
I have this dataset:
library(dplyr)
library(tidyr)
library(lubridate)
combined <- structure(list(country = c("Canada", "France", "Japan", "Brazil",
"Canada", "France", "Japan", "Brazil", "Canada", "France", "Japan",
"Brazil"), Red = c("yes", "no", "yes", "yes", "no", "yes", "no",
"yes", "yes", "yes", "yes", "yes"), Blue = c("no", "yes", "yes",
"no", "yes", "yes", "yes", "no", "yes", "no", "yes", "no"), Green = c("yes",
"yes", "no", "yes", "no", "yes", "yes", "yes", "yes", "yes",
"no", "yes"), time = c("2000-01-01", "2000-01-01", "2000-01-01",
"2000-01-01", "2000-02-01", "2000-02-01", "2000-02-01", "2000-02-01",
"2000-03-01", "2000-03-01", "2000-03-01", "2000-03-01")), class = "data.frame", row.names = c(NA,
-12L))
country Red Blue Green time
Canada yes no yes 2000-01-01
France no yes yes 2000-01-01
Japan yes yes no 2000-01-01
Brazil yes no yes 2000-01-01
Canada no yes no 2000-02-01
France yes yes yes 2000-02-01
Japan no yes yes 2000-02-01
Brazil yes no yes 2000-02-01
Canada yes yes yes 2000-03-01
France yes no yes 2000-03-01
Japan yes yes no 2000-03-01
Brazil yes no yes 2000-03-01
I want to answer the following question: For each country, each color was held between which time frames?
My current approach is using 2 steps:
long_data <- combined %>%
pivot_longer(
cols = c(Red, Blue, Green),
names_to = "color",
values_to = "has_color"
) %>%
mutate(time = as.Date(time)) %>%
arrange(country, color, time)
result <- long_data %>%
filter(has_color == "yes") %>%
group_by(country, color) %>%
mutate(
period_id = cumsum(c(1, diff(as.numeric(time)) > 31))
) %>%
group_by(country, color, period_id) %>%
summarise(
date_start = min(time),
date_end = ceiling_date(max(time), "month") - days(1),
.groups = "drop"
) %>%
select(country, color, date_start, date_end)
> result
# A tibble: 14 × 4
country color date_start date_end
1 Brazil Green 2000-01-01 2000-03-31
2 Brazil Red 2000-01-01 2000-03-31
3 Canada Blue 2000-02-01 2000-03-31
4 Canada Green 2000-01-01 2000-01-31
5 Canada Green 2000-03-01 2000-03-31
6 Canada Red 2000-01-01 2000-01-31
7 Canada Red 2000-03-01 2000-03-31
8 France Blue 2000-01-01 2000-02-29
9 France Green 2000-01-01 2000-03-31
10 France Red 2000-02-01 2000-03-31
11 Japan Blue 2000-01-01 2000-03-31
12 Japan Green 2000-02-01 2000-02-29
13 Japan Red 2000-01-01 2000-01-31
14 Japan Red 2000-03-01 2000-03-31
Is there a more straightforward way to solve this problem in a single step?