【问题标题】:Given a date range how to expand to the number of days per month in that range?给定一个日期范围,如何扩展到该范围内的每月天数?
【发布时间】:2018-08-15 07:21:45
【问题描述】:

案例:
给定的是一个数据框df,其中包括一个startDate 和一个endDate 列。我的目标是将df“转换”为一个新的数据框df_res,其中包含在间隔(startDate, endDate)中出现的每个月的一行,附加列yearmonthnumberOfDaysInMonth,所有类型诠释。

示例:
输入: df

  id    startDate     endDate  someOtherCol
   1   2017-09-23  2018-02-01          val1
   2   2018-01-01  2018-03-31          val2
 ...          ...         ...           ...

期望的输出: df_res

  id  year  month  numberOfDaysInMonth  someOtherCol
   1  2017      9                    8          val1
   1  2017     10                   31          val1
   1  2017     11                   30          val1
   1  2017     12                   31          val1
   1  2018      1                   31          val1
   1  2018      2                    1          val1
   2  2018      1                   31          val2
   2  2018      2                   28          val2
   2  2018      3                   31          val2
 ...   ...    ...                  ...           ... 

背景:
我对 R 比较陌生,但知道很棒的 dplyrlubridate 包。我只是没有设法以一种简洁的方式实现上述目标,即使在使用这些软件包时也是如此。我得到的最接近的是:Expand rows by date range using start and end date,但这不会产生该范围内包含的每月天数。

非常感谢任何帮助。

【问题讨论】:

  • 欢迎来到 SO!请阅读How to Ask!不要使用图片来展示你的数据,阅读stackoverflow.com/questions/5963269/…
  • seq.Date 可以通过month 访问,请参阅?seq.Date
  • 除此之外,请参阅stackoverflow.com/questions/6243088/…
  • 您好@jogo,感谢您的回复。我已经重新格式化了数据框。这样可以吗?
  • 谢谢@MichaelChirico。我检查了两个。我了解这些如何单独操作,但不知道如何应用它们以从dfdf_res。此外,后者查找给定月份中的天数,但我正在查找间隔 (startDate, endDate) 中包含的一个月中的天数(参见示例)。你知道该怎么做吗?

标签: r dplyr lubridate


【解决方案1】:

如果您不介意 data.table 解决方案,您可以在按 id、someOtherCol、年份和月份聚合之前在 startDate 和 endDate 之间创建一系列连续日期,如下所示:

dat[, .(Dates=seq(startDate, endDate, by="1 day")), by=.(id, someOtherCol)][,
    .N, by=.(id, someOtherCol, year(Dates), month(Dates))]

输出:

   id someOtherCol year month  N
1:  1         val1 2017     9  8
2:  1         val1 2017    10 31
3:  1         val1 2017    11 30
4:  1         val1 2017    12 31
5:  1         val1 2018     1 31
6:  1         val1 2018     2  1
7:  2         val2 2018     1 31
8:  2         val2 2018     2 28
9:  2         val2 2018     3 31

数据:

library(data.table)    
dat <- fread("id    startDate     endDate  someOtherCol
1   2017-09-23  2018-02-01          val1
2   2018-01-01  2018-03-31          val2")
datecols <- c("startDate", "endDate")
dat[, (datecols) := lapply(.SD, as.Date, format="%Y-%m-%d"), .SDcols=datecols]

【讨论】:

  • 感谢您的建议@chinsoon12。虽然这很好用,但我更喜欢tidyverse 解决方案,因为它更容易——至少对我来说——遵循它的逻辑。我的应用程序中的计算时间限制可能不会绑定,所以我没有将此方法与@AntoniosK 的计算性能提案进行比较。
【解决方案2】:

tidyverse 解决方案:

# example data
df = read.table(text = "
id    startDate     endDate  someOtherCol
1   2017-09-23  2018-02-01          val1
2   2018-01-01  2018-03-31          val2
", header=T, stringsAsFactors=F)

library(tidyverse)
library(lubridate)


df %>%
  mutate_at(vars(startDate, endDate), ymd) %>%                  # update to date columns (if needed)
  group_by(id) %>%                                              # for each id
  mutate(d = list(seq(startDate, endDate, by="1 day"))) %>%     # create a sequence of dates (as a list)
  unnest() %>%                                                  # unnest data
  group_by(id, year=year(d), month=month(d), someOtherCol) %>%  # group by those variables (while getting year and month of each date in the sequence)
  summarise(numberOfDaysInMonth = n()) %>%                      # count days
  ungroup()                                                     # forget the grouping

# # A tibble: 9 x 5
#      id  year month someOtherCol numberOfDaysInMonth
#   <int> <dbl> <dbl> <chr>                      <int>
# 1     1  2017     9 val1                           8
# 2     1  2017    10 val1                          31
# 3     1  2017    11 val1                          30
# 4     1  2017    12 val1                          31
# 5     1  2018     1 val1                          31
# 6     1  2018     2 val1                           1
# 7     2  2018     1 val2                          31
# 8     2  2018     2 val2                          28
# 9     2  2018     3 val2                          31

【讨论】:

  • 像魅力一样工作!非常感谢,@AntoniosK。
猜你喜欢
  • 1970-01-01
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多