floor_date 在 mutate 和 ifelse 中不起作用

floor_date not working in mutate and ifelse

我正在尝试编写一个泛化聚合函数,用户可以在其中指定聚合级别,或者他们可以聚合所有研究日期的数据。 floor_date 只转换第一个日期。为什么?我该如何解决这个问题?

library(dplyr)
library(lubridate)

sTerm <- "year" # month, bimonth, quarter, season, halfyear and year, custom
sCustom <- "2023-2025"

dfDatasetOutput  <- data.frame(
  valDate=seq(as.Date("2023-01-01"), as.Date("2025-12-01"), by = "month"), 
  cat1=rnorm(36, 3500, 1000),
  cat2=rnorm(36, 2.5, 5)
)

dfDatasetOutput %>%
  mutate(valDate=ifelse(toupper(sTerm)=="CUSTOM", 
                          sCustom, 
                          as.character(floor_date(valDate, sTerm)))) 

# this works just fine
dfDatasetOutput %>%
  mutate(valDate=as.character(floor_date(valDate, sTerm)))

问题并非源于 floor_date,而是源于您对 ifelse 的使用。根据其手册:

ifelse(test, yes, no)
ifelse returns a value with the same shape as test which is filled
with elements selected from either yes or no depending on whether 
the element of test is TRUE or FALSE.

您的测试是 toupper(sTerm)=="CUSTOM",它是单个逻辑元素 TRUE 或 FALSE(或 NA)。所以 ifelse 的输出将是单个元素。如果测试为假,它将从 as.character(floor_date(valDate, sTerm)) 中获取此元素。它只需要一个,所以会取第一个。然后 mutate 将这个单个值回收到列的长度。

如果您希望输出的长度与 valDate 相同,解决方法是重复您的测试,以便获得所需长度的向量作为测试:

dfDatasetOutput %>%
  mutate(valDate=ifelse(rep(toupper(sTerm)=="CUSTOM",nrow(dfDatasetOutput)), 
                        sCustom, 
                        as.character(floor_date(valDate, sTerm)))) 

为避免无意中使用 ifelse,请考虑使用 if_else 来检查对象长度。