【问题标题】:Format date as Year/Quarter将日期格式化为年/季度
【发布时间】:2014-03-01 13:21:33
【问题描述】:

我有以下数据框:

Data <- data.frame(
  date = c("2001-01-01", "2001-02-01", "2001-03-01", "2001-04-01", "2001-05-01", "2001-06-01"),
  qtr = c("NA", "NA","NA","NA","NA","NA")
)

我想用年/季填充 Data$qtr - f.e. 01/01(我需要这种格式!)。

我写了一个函数:

fun <- function(x) { 
  if(x == "2001-01-01" | x == "2001-02-01" | x == "2001-03-01") y <- "01/01"
  if(x == "2001-04-01" | x == "2001-05-01" | x == "2001-06-01") y <- "01/02"
  return(y)
}
n$qtr <- sapply(n$date, fun)

但它不起作用。我总是收到错误消息:

Error in FUN(X[[1L]], ...) : Object 'y' not found

为什么?

【问题讨论】:

  • 您可能会遇到该错误,因为您的某个日期在任一 if 表达式中都不匹配。所以y 从未在fun 中分配。

标签: r date


【解决方案1】:

你需要明确Vectorize你的函数:

fun_v <- Vectorize(fun, "x")
fun_v(Data$date)
#[1] "01/01" "01/01" "01/01" "01/02" "01/02" "01/02"

但是,当涉及到或多或少的标准任务(例如日期时间操作)时,总有一个可用的解决方案:

library(zoo)
yq <- as.yearqtr(Data$date, format = "%Y-%m-%d")
yq
#[1] "2001 Q1" "2001 Q1" "2001 Q1" "2001 Q2" "2001 Q2" "2001 Q2"

要转换为您的特定格式,请使用

format(yq, format = "%y/0%q")
#[1] "01/01" "01/01" "01/01" "01/02" "01/02" "01/02"

【讨论】:

  • 谢谢。使用 "format(z, format="%y/0%q") 会很完美。但结果我得到 "01/0q" 等等
  • 您可能忘记了q 之前的% 符号。
【解决方案2】:

我一直喜欢使用 lubridate 处理日期的包。超级光滑。 quarter 函数会找到季度(当然),然后将其与年份配对。

library(lubridate)
Data <- Data %>%
  mutate(qtr = paste0(substring(year(date),3,4),"/0",quarter(date))) 

如果您不熟悉来自magrittr%&gt;%,第一行基本上是说“使用名为Data 的数据框”,第二行说“变异(或添加)一个名为qtr 的列”

编辑 2021 年第二季度

如果“YY/QQ”格式不重要,那么获取年份和季度的一种快速安全的方法是:

library(lubridate)
Data %>%
  mutate(qtr = quarter(date, with_year = T))

【讨论】:

  • 或与年份参数一起使用:quarter(x, with_year = TRUE)
【解决方案3】:

使用基函数:

Data$date <- as.Date(Data$date)
Data$qtr <- paste(format(Data$date, "%y"), 
                  sprintf("%02i", (as.POSIXlt(Data$date)$mon) %/% 3L + 1L), 
                  sep="/")

#         date   qtr
# 1 2001-01-01 01/01
# 2 2001-02-01 01/01
# 3 2001-03-01 01/01
# 4 2001-04-01 01/02
# 5 2001-05-01 01/02
# 6 2001-06-01 01/02

【讨论】:

    【解决方案4】:

    另一种选择是:

    Data$qtr <- lubridate::quarter(Data$date, with_year = T)
    

    【讨论】:

      【解决方案5】:

      我在 R 中使用 quarters()sub() 制作了类似的格式:

      Data$qtr <- paste(format(Data$date, "%y/"), 0, 
                        sub( "Q", "", quarters(Data$date) ), sep = "")
      

      【讨论】:

        【解决方案6】:

        data.table 包及其IDate 类具有一些很好的便利功能(例如quarter()year()),类似于lubridate 的可用功能。 paste0()他们随你便。

        Data <- data.frame(
          date = c("2001-01-01", "2001-02-01", "2001-03-01",
                   "2001-04-01", "2001-05-01", "2001-06-01")
        )
        
        require(data.table)
        setDT(Data)
        
        Data[ , date := as.IDate(date) ] # data.table s integer based date class
        Data[ , qtr := paste0(year(date), '/', quarter(date)) ]
        # your specific format
        Data[ , qt2 := paste0(substr(year(date),3,4), '/', '0', quarter(date)) ]
        

        【讨论】:

          【解决方案7】:

          另一种(更长的)方式 使用 if 语句的方法是这样的:

          month <- as.numeric(format(date, format = "%m"))[1]
          
          if (month < 4) {
              quarter <- paste( format(date, format = "%Y")[1], "Q1", sep="-")
          } else if (month > 3 & month < 7) {
              quarter <- paste( format(date, format = "%Y")[1], "Q2", sep="-")            
          } else if (month > 6 & month < 10) {
              quarter <- paste( format(date, format = "%Y")[1], "Q3", sep="-")
          } else if (month > 9) {
              quarter <- paste( format(date, format = "%Y")[1], "Q4", sep="-")
          }
          

          返回格式为:

          的字符串
          > quarter
          [1] "2001-Q1"
          

          然后你可以使用循环来扩展它。

          【讨论】:

            【解决方案8】:
            yq=function(x,prefix="%Y",combine="Q") paste0(ifelse(is.null(prefix),"",format(x,"%Y")),floor(as.numeric(format(x,"%m"))/3-1e-3)+1,sep=combine)
            

            这提供了返回任何包含四分之一的格式的灵活性

            不需要chron或zoo

            至于你的例子

            yq(as.Date("2013-04-30"),prefix="%y",combine="/0")
            > [1] "13/02"
            

            【讨论】:

            • 使用 yearqtr,您可以轻松添加季度和执行其他操作,您还可以绘制 yearqtr 对象并使其正确显示,但不能使用字符串。
            【解决方案9】:

            如果有人正在寻找 21 年第一季度的格式,例如 21 年第 1 季度,我使用上面的@Roland 答案并对以下内容进行了小改动:

            paste(sprintf("%2i", (as.POSIXlt(Notional$Date)$mon) %/% 3L + 1L), format(Notional$Date, "%y"),sep="Q")
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-11-18
              • 2015-09-13
              • 1970-01-01
              • 2021-07-25
              • 1970-01-01
              • 1970-01-01
              • 2023-01-22
              • 1970-01-01
              相关资源
              最近更新 更多