【问题标题】:generate seq of quarter date in R在R中生成季度日期的序列
【发布时间】:2016-05-27 02:07:27
【问题描述】:

我是 R 新手,我是否有一个看起来像这样的数据框。

 Date       A       B
1990 Q1     2       3
     Q2     4       2
     Q3     7       6
     Q4     5       3
1991 Q1     7       6
     Q2     1       8
     Q3     7       6
     Q4     9       2
1992 Q1     1       7
     Q2     4       6
     Q3     1       3
     Q4     5       8
...

该列一直延伸到行尾,并且开始日期和结束日期都不是固定的,因为数据会不断更新。我想将日期列格式化为日期类并实现如下效果:

 Date       A       B
1990 Q1     2       3
1990 Q2     4       2
1990 Q3     7       6
1990 Q4     5       3
1991 Q1     7       6
1991 Q2     1       8
1991 Q3     7       6
1991 Q4     9       2
1992 Q1     1       7
1992 Q2     4       6
1992 Q3     1       3
1992 Q4     5       8
...

我想在左侧重新创建一个新的日期列,并使用数据提供的第一个日期(即“1990 Q1”)作为开始日期,并根据行数使用长度。正在考虑使用 seq.和 as.yearqtr 命令,但似乎无法为其制定正确的代码。有人知道更好的方法吗?

【问题讨论】:

  • 我应该只接受一个答案吗?我不确定发生了什么,因为我尝试接受多个答案,但绿色勾号在一段时间后消失了。
  • 我明白了。我在那里道歉,我不知道,因为我是新人

标签: r date


【解决方案1】:

要使用zoo 包中的yearqtr 函数创建年-季时间序列,您可以首先将df$Date 值拆分为年和季度字符串,使用na.locf,同样来自@987654325 @包,用上一行的值填充年份的缺失值,然后转换为带有年份季度日期的zoo时间序列。代码看起来像

library(zoo)
# split Date into year and quarter strings
tmp <- t(sapply(strsplit((df$Date), " "), function(x) if(length(x)==1) c(NA, x) else x)) 
# use na.locf to replace NA with previous year
tmp <- paste(na.locf(tmp[,1]), tmp[,2])
# transform df into a zoo time series object with yearqtr dates
df_zoo <- zoo(df[,-1], order.by = as.yearqtr(tmp))

【讨论】:

    【解决方案2】:

    我们可以在base R 中执行此操作。使用grepcumsum 创建一个分组变量,从“日期”中提取数字子字符串,使用ave'' 值替换为年份值,然后将paste 替换为使用@ 提取的季度子字符串987654327@.

    df$Date <-  paste(ave(sub("\\s*Q.", "", df$Date),
         cumsum(grepl("^\\d+", df$Date)), FUN = function(x) x[nzchar(x)]),
       sub("^\\d+\\s+", "", df$Date))
    df$Date
    #[1] "1990 Q1" "1990 Q2" "1990 Q3" "1990 Q4" "1991 Q1" "1991 Q2" 
    #[7] "1991 Q3" "1991 Q4" "1992 Q1" "1992 Q2" "1992 Q3" "1992 Q4"
    

    不需要额外的包。


    如果我们需要打包解决方案,可以使用data.table

    library(data.table)
    library(stringr)
    setDT(df)[, Date:=sub("^(Q.*)", paste0(word(Date[1],1), " \\1") , Date), 
                                                     cumsum(grepl("^\\d+" , Date))]
    df
    #       Date A B
    # 1: 1990 Q1 2 3
    # 2: 1990 Q2 4 2
    # 3: 1990 Q3 7 6
    # 4: 1990 Q4 5 3
    # 5: 1991 Q1 7 6
    # 6: 1991 Q2 1 8
    # 7: 1991 Q3 7 6
    # 8: 1991 Q4 9 2
    # 9: 1992 Q1 1 7
    #10: 1992 Q2 4 6
    #11: 1992 Q3 1 3
    #12: 1992 Q4 5 8
    

    数据

    df <- structure(list(Date = c("1990 Q1", "Q2", "Q3", "Q4", "1991 Q1", 
    "Q2", "Q3", "Q4", "1992 Q1", "Q2", "Q3", "Q4"), A = c(2L, 4L, 
    7L, 5L, 7L, 1L, 7L, 9L, 1L, 4L, 1L, 5L), B = c(3L, 2L, 6L, 3L, 
    6L, 8L, 6L, 2L, 7L, 6L, 3L, 8L)), .Names = c("Date", "A", "B"
    ), row.names = c(NA, -12L), class = "data.frame")
    

    【讨论】:

      【解决方案3】:

      这是创建您正在寻找的序列的直接方法:

      numrows<-10  #number of elements desired
      
      #create the sequence of Date objects
      qtrseq<-seq(as.Date("1990-01-01"), by="quarter", length.out = numrows)
      
      #created vector for the formatted display
      qtrformatted<-paste(as.POSIXlt(qtrseq)$year+1900, quarters(qtrseq))
      

      此方法和其他列出的解决方案的缺点是丢失了 Date 对象。在基础 R 中没有很好的方法来格式化 Q1、Q2 ......并使对象保持为 Date 对象。根据您的应用程序,最好将日期序列存储在数据框中,并将该语句仅用于 qtr 格式的输出目的。 祝你好运。

      【讨论】:

        【解决方案4】:

        假设Date 是单个字符列,这里有一个使用tidyr 的选项:

        library(tidyr)
        
        # separate date into year and quarter, inserting NAs in year as necessary
        df %>% separate(Date, into = c('year', 'quarter'), fill = 'left') %>% 
            # fill NAs with previous value
            fill(year) %>% 
            # join year and quarter back into a single column
            unite(Date, year, quarter, sep = ' ')
        
        #       Date A B
        # 1  1990 Q1 2 3
        # 2  1990 Q2 4 2
        # 3  1990 Q3 7 6
        # 4  1990 Q4 5 3
        # 5  1991 Q1 7 6
        # 6  1991 Q2 1 8
        # 7  1991 Q3 7 6
        # 8  1991 Q4 9 2
        # 9  1992 Q1 1 7
        # 10 1992 Q2 4 6
        # 11 1992 Q3 1 3
        # 12 1992 Q4 5 8
        

        数据

        df <- structure(list(Date = structure(c(1L, 4L, 5L, 6L, 2L, 4L, 5L, 
                6L, 3L, 4L, 5L, 6L), .Label = c("1990 Q1", "1991 Q1", "1992 Q1", 
                "Q2", "Q3", "Q4"), class = "factor"), A = c(2L, 4L, 7L, 5L, 7L, 
                1L, 7L, 9L, 1L, 4L, 1L, 5L), B = c(3L, 2L, 6L, 3L, 6L, 8L, 6L, 
                2L, 7L, 6L, 3L, 8L)), .Names = c("Date", "A", "B"), class = "data.frame", row.names = c(NA, 
                -12L))
        

        【讨论】:

          【解决方案5】:

          你可以试试这个

          library(dplyr); library(stringr); library(zoo)
          df %>% mutate(Date = paste(na.locf(str_extract(Date, "^[0-9]{4}")),     
                                             str_extract(Date, "Q[1-4]$"), sep = " "))
                Date A B
          1  1990 Q1 2 3
          2  1990 Q2 4 2
          3  1990 Q3 7 6
          4  1990 Q4 5 3
          5  1991 Q1 7 6
          6  1991 Q2 1 8
          7  1991 Q3 7 6
          8  1991 Q4 9 2
          9  1992 Q1 1 7
          10 1992 Q2 4 6
          11 1992 Q3 1 3
          12 1992 Q4 5 8
          

          【讨论】:

            猜你喜欢
            • 2021-10-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-07-26
            • 1970-01-01
            相关资源
            最近更新 更多