【问题标题】:Subset a dataframe between 2 dates在 2 个日期之间设置数据框的子集
【发布时间】:2021-11-09 23:00:40
【问题描述】:

自 1993 年以来,我一直在处理巴西指数 (IBOV) 的每日回报,我试图找出对两个日期之间的时段进行子集化的最佳方法。

数据框(IBOV_RET)如下:

head(IBOV_RET)
        DATE    1D_RETURN
1 1993-04-28 -0.008163265
2 1993-04-29 -0.024691358
3 1993-04-30  0.016877637
4 1993-05-03  0.000000000
5 1993-05-04  0.033195021
6 1993-05-05 -0.012048193
...

我将 2 个变量 DATE1DATE2 设置为日期

DATE1 <- as.Date("2014-04-01")
DATE2 <- as.Date("2014-05-05")

我能够使用此代码创建一个新子集:

TEST <- IBOV_RET[IBOV_RET$DATE >= DATE1 & IBOV_RET$DATE <= DATE2,]

它有效,但我想知道是否有更好的方法来对两个日期之间的数据进行子集化,可能使用subset

【问题讨论】:

  • 如果您将数据框命名为 df 并将日期命名为 t1t2,则可以得到更短的名称,例如:df[df$Date %in% t1:t2, ]。澄清一下,t1:t2 适用于日期,因此您不需要有不等式。

标签: r date subset


【解决方案1】:
Test = IBOV_RET[IBOV_RET$Date => "2014-04-01" | IBOV_RET$Date <= "1993-05-04"]

这里我使用“或”函数 |其中数据应大于特定数据或数据应小于或等于该日期。

【讨论】:

  • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。
  • @Yunnosch 的评论总是需要牢记,但尤其是在这里已经有几个答案已经被社区。您的答案与现有答案有何不同?在什么情况下可能更受欢迎?
  • 抱歉回复晚了。
【解决方案2】:

您可以在简单地将字符串转换为日期后使用 R 的 between() 函数:

df %>%
    filter(between(date_column, as.Date("string-date-lower-bound"), as.Date("string-date-upper-bound")))

【讨论】:

    【解决方案3】:

    我相信lubridate 可以在这里提供帮助;

    daterange <- interval(DATE1, DATE2)
    TEST <- IBOV_RET[which(Date %within% daterange),]
    

    【讨论】:

      【解决方案4】:

      您可以将subset() 函数与&amp; 运算符一起使用:

      subset(IBOV_RET, DATE1> XXXX-XX-XX & DATE2 < XXXX-XX-XX)
      

      更新为更“面向 tidyverse”的方法:

      IBOV_RET %>%
        filter(DATE1 > XXXX-XX-XX, DATE2 < XXXX-XX-XX) #comma same as &
      

      【讨论】:

        【解决方案5】:

        怎么样:

        DATE1 <- as.Date("1993-04-29")
        DATE2 <- as.Date("1993-05-04")
        
        # creating a data range with the start and end date:
        dates <- seq(DATE1, DATE2, by="days")
        
        IBOV_RET <- subset(IBOV_RET, DATE %in% dates)
        

        【讨论】:

          【解决方案6】:

          我有点喜欢 dplyr
          所以如果你

          >library("dplyr")
          

          然后,就像你做的那样:

          >Date1<-as.Date("2014-04-01")  
          >Date2<-as.Date("2014-05-05")
          

          终于

          >test<-filter(IBOV_RET, filter(DATE>Date1 & DATE<Date2))
          

          【讨论】:

          • 这样调用filter 两次没有意义
          【解决方案7】:

          正如@MrFlick 已经指出的那样,您无法绕过子集的基本逻辑。使您更容易对特定 data.frame 进行子集化的一种方法是定义一个函数,该函数在您的示例中采用两个输入,例如 DATE1DATE2,然后根据这些子集参数返回 IBOV_RET 的子集.

          myfunc <- function(x,y){IBOV_RET[IBOV_RET$DATE >= x & IBOV_RET$DATE <= y,]}
          
          DATE1 <- as.Date("1993-04-29")
          DATE2 <- as.Date("1993-05-04")
          
          Test <- myfunc(DATE1,DATE2)    
          
          #> Test
          #        DATE  X1D_RETURN
          #2 1993-04-29 -0.02469136
          #3 1993-04-30  0.01687764
          #4 1993-05-03  0.00000000
          #5 1993-05-04  0.03319502
          

          您也可以直接将具体日期输入myfunc

          myfunc(as.Date("1993-04-29"),as.Date("1993-05-04")) #will produce the same result
          

          【讨论】:

            【解决方案8】:

            没有其他真正的方法可以提取日期范围。逻辑也与提取一系列数值相同,您只需要像您所做的那样进行显式日期转换。您可以像使用 subsetwith 的任何其他子集任务一样缩短子集。您可以使用cut 将范围划分为多个区间(存在特定的cut.Date 过载)。但是基本 R 没有任何方法来指定 Date 文字,因此您无法避免转换。我无法想象您可能想到的其他类型的语法。

            【讨论】:

              猜你喜欢
              • 2019-01-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-02-07
              • 1970-01-01
              相关资源
              最近更新 更多