如何在 R 中创建多个日期范围的子集

How to create subsets of multiple date ranges in R

我有一个名为 'df' 的包含日期和数字的数据框。我有另一个数据框,其开始日期和结束日期称为 'date_ranges'。

我的目标是 filter/subset df 以便它只显示 start/end 列的每一行中的 start/end 日期。到目前为止,这是我的代码:


    df_date <- as.Date((as.Date('2010-01-01'):as.Date('2010-04-30')))
    df_numbers <- c(1:120)
    df <- data.frame(df_date, df_numbers)


    start_dates <- as.Date(c("2010-01-06", "2010-02-01", '2010-04-15'))
    end_dates <- as.Date(c("2010-01-23", "2010-02-06", '2010-04-29'))
    date_ranges <- data.frame(start_dates, end_dates)

    # Attempting to filter df by start and end dates
    for (i in range(date_ranges$start_dates)){
      for (j in range(date_ranges$end_dates)){
        print (
          df %>%
          filter(between(df_date, i, j)))
      }

    }

嵌套for循环的第一个和第三个结果是我想要的,但第二个结果不是。第一个和第三个给出了它们各自行之间 df 的日期和值,但第二个结果是从最早日期到最晚日期的范围。如何修复此循环以排除第二个结果?

您可以尝试遍历索引

for (i in seq_along(date_ranges$start_dates)){
    print (
      df %>%
        filter(between(df_date, date_ranges$start_dates[i], date_ranges$end_dates[i])))
}

基础 R 解决方案:

# Your data creation can be simplified: 
df <- data.frame(df_date = seq.Date(as.Date('2010-01-01', "%Y-%m-%d"), as.Date('2010-04-30', "%Y-%m-%d"),
                                    by = 1), df_numbers = c(1:120))

# Store start and end date vectors to filter the data.frame: 
start_dates <- as.Date(c("2010-01-06", "2010-02-01", '2010-04-15'))
end_dates <- as.Date(c("2010-01-23", "2010-02-06", '2010-04-29'))

# Subset the data to extract records with matching dates: df => stdout (Console
df[df$df_date %in% c(start_dates, end_dates),]

tidyverse 方法可能是在 startend_dates 之间创建一个序列,并与 df 连接以仅保留范围内的日期。

library(dplyr)

date_ranges %>%
  mutate(df_date = purrr::map2(start_dates, end_dates, seq, "day")) %>%
  tidyr::unnest(df_date) %>%
  select(-start_dates, -end_dates) %>%
  left_join(df, by = 'df_date')

# A tibble: 39 x 2
#   df_date    df_numbers
#   <date>          <int>
# 1 2010-01-06          6
# 2 2010-01-07          7
# 3 2010-01-08          8
# 4 2010-01-09          9
# 5 2010-01-10         10
# 6 2010-01-11         11
# 7 2010-01-12         12
# 8 2010-01-13         13
# 9 2010-01-14         14
#10 2010-01-15         15
# … with 29 more rows