部分原因取决于您使用的是气象季节还是天文季节 (https://www.almanac.com/content/first-day-seasons)。或者,如果您想按天而不是按月微调一个季节。这是一个允许您这样做的建议。
seasons <- as.Date(paste0("2021-", c("01-01", "03-01", "06-01", "09-01", "12-01")))
seasons <- as.POSIXlt(seasons)$yday
seasons <- setNames(seasons, c("winter", "spring", "summer", "fall", "winter"))
seasons
# winter spring summer fall winter
# 0 59 151 243 334
library(dplyr)
library(lubridate)
as_tibble(df) %>%
mutate(
yday = yday(date),
season = names(seasons)[findInterval(yday, c(seasons, Inf))]
) %>%
sample_n(10)
# # A tibble: 10 x 6
# date x y ID yday season
# <date> <dbl> <dbl> <int> <int> <chr>
# 1 2010-02-13 79471. 862415. 4 43 winter
# 2 2010-10-23 61796. 813429. 1 295 fall
# 3 2011-12-09 65958. 808064. 3 342 winter
# 4 2010-05-29 65872. 841309. 4 148 spring
# 5 2010-03-07 63789. 869548. 1 65 spring
# 6 2012-02-12 67605. 859081. 3 42 winter
# 7 2011-04-19 79034. 883803. 4 108 spring
# 8 2011-03-16 69658. 832297. 5 74 spring
# 9 2011-12-29 68793. 881267. 3 362 winter
# 10 2012-04-24 70784. 805323. 5 114 spring
从这里开始,让我们筛选出至少有两个季节之一的年份。不幸的是,我们的数据分布相当均匀,
as_tibble(df) %>%
mutate(
year = year(date),
yday = yday(date),
season = names(seasons)[findInterval(yday, c(seasons, Inf))],
) %>%
group_by(year) %>%
count(season) %>%
tidyr::pivot_wider(year, names_from = season, values_from = n)
# # A tibble: 3 x 5
# # Groups: year [3]
# year fall spring summer winter
# <dbl> <int> <int> <int> <int>
# 1 2010 91 92 92 90
# 2 2011 91 92 92 90
# 3 2012 28 92 92 58
所以我们不知道它是否真的在做我们想要的。我会人为地删除一些数据来测试我们想要的逻辑:
as_tibble(df) %>%
mutate(
year = year(date),
yday = yday(date),
season = names(seasons)[findInterval(yday, c(seasons, Inf))],
) %>%
filter(year > 2010 | season %in% c("fall", "winter")) %>% # artificial, for testing
group_by(year) %>%
count(season) %>%
tidyr::pivot_wider(year, names_from = season, values_from = n)
# # A tibble: 3 x 5
# # Groups: year [3]
# year fall winter spring summer
# <dbl> <int> <int> <int> <int>
# 1 2010 91 90 NA NA
# 2 2011 91 90 92 92
# 3 2012 28 58 92 92
从这里,我们添加一个分组过滤器:
as_tibble(df) %>%
mutate(
year = year(date),
yday = yday(date),
season = names(seasons)[findInterval(yday, c(seasons, Inf))],
) %>%
filter(year > 2010 | season %in% c("fall", "winter")) %>% # artificial, for testing
group_by(year) %>%
filter(all(c("winter", "summer") %in% season)) %>% # this is the new line
sample_n(10)
# # A tibble: 20 x 7
# # Groups: year [2]
# date x y ID year yday season
# <date> <dbl> <dbl> <int> <dbl> <dbl> <chr>
# 1 2011-02-13 61686. 815664. 4 2011 44 winter
# 2 2011-10-23 75448. 849477. 1 2011 296 fall
# 3 2011-07-15 75901. 840969. 1 2011 196 summer
# 4 2011-05-29 66108. 811565. 4 2011 149 spring
# 5 2011-03-07 70298. 831304. 1 2011 66 spring
# 6 2011-09-18 73951. 875712. 1 2011 261 fall
# 7 2011-08-04 64917. 860239. 1 2011 216 summer
# 8 2011-11-29 78909. 802692. 3 2011 333 fall
# 9 2011-01-07 66441. 868062. 2 2011 7 winter
# 10 2011-06-16 64583. 889124. 2 2011 167 summer
# 11 2012-05-09 78725. 862934. 5 2012 130 spring
# 12 2012-08-12 67767. 871229. 5 2012 225 summer
# 13 2012-06-28 62354. 898829. 5 2012 180 summer
# 14 2012-05-26 62373. 819059. 2 2012 147 spring
# 15 2012-06-21 68019. 896370. 3 2012 173 summer
# 16 2012-01-22 61753. 872778. 2 2012 22 winter
# 17 2012-03-18 64490. 810292. 3 2012 78 spring
# 18 2012-08-15 76048. 875765. 3 2012 228 summer
# 19 2012-09-15 65386. 885431. 4 2012 259 fall
# 20 2012-04-19 60072. 895292. 5 2012 110 spring
(与 2010 年相比没有什么,我们所期望的。)
数据
我在随机数据中使用了可重复性种子:
set.seed(42)
date <- rep_len(seq(dmy("01-01-2010"), dmy("31-12-2013"), by = "days"),1000)
ID <- rep(seq(1, 5), 100)
df <- data.frame(date = date,
x = runif(length(date), min = 60000, max = 80000),
y = runif(length(date), min = 800000, max = 900000),
ID)
head(df)
# date x y ID
# 1 2010-01-01 78296.1209 884829.322 1
# 2 2010-01-02 78741.5083 806274.633 2
# 3 2010-01-03 65722.7907 881984.509 3
# 4 2010-01-04 76608.9525 853936.029 4
# 5 2010-01-05 72834.9104 849902.010 5
# 6 2010-01-06 70381.9190 802222.732 1