【问题标题】:Number of months between two dates for each year in rr 中每年两个日期之间的月数
【发布时间】:2020-05-31 20:42:52
【问题描述】:

我正在处理如下所示的数据:

name       start_date        end_date
 A         1993-06-25       1993-11-04
 B         2003-12-12       2004-07-20
 C         1997-06-11       2000-11-27
 D         1990-06-29       1992-07-02

我想计算名字跨越的每一年的月数。

让数据看起来像这样:

name  year number_months
A     1993    5
B     2003    1
B     2004    7
C     1997    6
C     1998   12
C     1999   12
C     2000   11
D     1990    6
D     1991   12
D     1992    7

这是一个可重现的例子:

name <- c("A", "B", "C", "D")
start_date <- as.Date(c("1993-06-25", "2003-12-12", "1997-06-11", "1990-06-29"))
end_date <- as.Date(c("1993-11-04", "2004-07-20", "2000-11-27", "1992-07-02"))

df <- data.frame(name, start_date, end_date)

【问题讨论】:

  • 因为我把 2003-12-12 算作包括 2003 年的 1 个月,其余的算作 2004 年的 7 个月
  • 是的,没错。在所有名称中,我想知道每个名称涵盖的每一年有多少个月。
  • 好的,知道了。我认为最简单的方法是在 'year' 之前从 start_date 到 'end_date' 执行 seq
  • @akrun,别担心。我将修改问题并使其更清楚。
  • 只做一张年表table(format(seq(df[2, 2], df[2, 3], by = 'months'), '%Y'))

标签: r date monthcalendar data-management


【解决方案1】:

tidyverse 中的一个选项

library(dplyr)
library(tidyr)
library(purrr)
library(tibble)
library(lubridate)
df %>% 
   transmute(name,  out = map2(start_date, end_date,
     ~ seq(.x, .y, by = 'months') %>% 
           year %>%
           table %>%
           enframe(name = 'year', value = 'number_months'))) %>% 
   unnest(c(out))

或者interval的另一个选项

df %>% 
     transmute(name,  out = map2(start_date, end_date,
          ~ tibble(date = seq(.x, .y, by = 'months'), year = year(date)) %>%
               group_by(year) %>%
               summarise(number_months = interval(floor_date(first(date), 'month'), 
                   ceiling_date(last(date), 'month')) %/% months(1)) )) %>%
     unnest(c(out))

或者在base R(扩展@rawr的解决方案)

do.call(rbind, Map(function(x, y, z) 
 cbind(name = z, stack(table(format(seq(x, y, by = 'months'), 
  '%Y')))), df$start_date, df$end_date, df$name))

或者正如@rawr 评论的那样,也可以使用data.frame 替换stack

do.call(rbind, Map(function(x, y, z) 
     cbind(name = z, data.frame(table(format(seq(x, y, by = 'months'), 
       '%Y')))), df$start_date, df$end_date, df$name))

【讨论】:

  • 我几乎在 cmets 中击败了你 :} 如果你使用 data.frame 而不是 stack,列顺序是固定的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-02
  • 2014-04-07
  • 1970-01-01
  • 2014-10-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多