【问题标题】:Writing vectorized function with lubridate::month() to produce fiscal year使用 lubridate::month() 编写向量化函数以生成财政年度
【发布时间】:2020-02-04 23:46:31
【问题描述】:

我正在编写一个函数来获取日期并输出(6 月 30 日)财政年度月份,其中 7 月是财年第 1 个月,8 月是 2 月,6 月是 12 月。

例如,给定两年的日期,我希望此数据的输出为 c(1:12, 1:12)

data.frame(perf_dt = seq.Date(from = as.Date("2019-07-01"),
                              to   = as.Date("2021-06-01"),
                              by   = "month"))

我目前的功能是这个。它包括可选择允许输出标签的逻辑。

FY_mo <- function(date, label = F, abbrev = F) {
  a <- (5 + (lubridate::month(date) %% 12)) + 1
  CY_num = lubridate::month(date)
  ifelse(!label, a,
          ifelse(abbrev,
                  month.abb[CY_num],
                  month.name[CY_num]))
}

当我给它提供单独的日期时,这很有效。例如,testthat 的这个测试通过了:

test_that("FY_mo works on indiv input dates", {
  expect_equal(7, FY_mo(as.Date("2020-01-01")))
  expect_equal("January", FY_mo(as.Date("2020-01-01"), label = TRUE))
  expect_equal("Jan", FY_mo(as.Date("2020-01-01"), label = TRUE, abbrev = TRUE))
})

但是当我给它一个向量时它不起作用。下面的代码输出所有“13”。

data.frame(perf_dt = seq.Date(from = as.Date("2019-07-01"),
                                             to =   as.Date("2021-06-01"),
                                             by = "month")) %>%
                 dplyr::mutate(FY_mo = FY_mo(perf_dt)) %>%
                 dplyr::pull(FY_mo)
#[1] 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13

我的错误在哪里?有没有更好的方法来构造函数以产生正确的向量输出?

【问题讨论】:

  • 或者直接使用Vectorize:FY_mo &lt;- Vectorize(FY_mo)

标签: r vectorization lubridate


【解决方案1】:

这不是一个错误,但是因为我们使用ifelse 来检查这里的条件并且ifelse 返回一个与test 长度相同的向量。由于我们的 test 的长度为 1 (length(!label)),它只返回第一个值并回收它。在这里,因为我们有一个条件要检查,我们可以使用if/else 而不是ifelse,这将避免这个问题。

FY_mo <- function(date, label = F, abbrev = F) {
  a <- match(lubridate::month(date), c(7:12, 1:6))
  CY_num = lubridate::month(date)
  if(!label) a
  else if (abbrev) month.abb[CY_num]
       else month.name[CY_num]       
}

data.frame(perf_dt = seq.Date(from = as.Date("2019-07-01"),
                              to =   as.Date("2021-06-01"),
                              by = "month")) %>%
  dplyr::mutate(FY_mo = FY_mo(perf_dt)) %>%
  dplyr::pull(FY_mo)

#[1] 1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9 10 11 12

【讨论】:

  • 谢谢。所需的输出是c(1:12, 1:12)。我再看看。
  • @JonSpring 我明白了。我猜这行的逻辑需要更改a &lt;- (5 + (lubridate::month(date) %% 12)) + 1
  • 谢谢!我改成a &lt;- ((5 + lubridate::month(date)) %% 12) + 1 并且成功了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 2023-03-18
  • 2014-07-20
  • 1970-01-01
相关资源
最近更新 更多