【问题标题】:Filter dataframe based on a date that may or may not be contained in the dataframe根据可能包含或不包含在数据框中的日期过滤数据框
【发布时间】:2016-10-18 05:30:42
【问题描述】:

我有一个数据框 (df),如下所示:

    derv        market       date
 -10.7803563 S&P 500 Index 2008-01-02
 -15.6922552 S&P 500 Index 2008-01-03
 -15.7648483 S&P 500 Index 2008-01-04
 -10.2294744 S&P 500 Index 2008-01-07
  -0.5918593 S&P 500 Index 2008-01-08
   8.1518987 S&P 500 Index 2008-01-09
 .....
  84.1518987 S&P 500 Index 2014-12-31

我想在 df 中找到特定日期之前的 10 个交易日。例如,2008-01-12。

我曾想过像下面这样使用 dplyr:

df %>% select(derv,Market,date) %>%
            filter(date > 2008-01-12 - 10 & Date <2008-01-12)

但我遇到的问题是如何索引特定日期前的 10 个交易日。我上面的代码不起作用,我不知道在使用 dplyr 的情况下如何处理。

另一个令人担忧的问题是特定日期(例如 2008-01-12)可能在 df 中,也可能不在 df 中。如果具体在df,我想我只需要回溯9天就可以了;但它不在 df 中,我需要返回 10 个索引。我不确定我在这里是否正确,但这是让我感到困惑的部分。

非常感谢任何见解。

【问题讨论】:

    标签: r date dplyr


    【解决方案1】:

    使用dplyrdata.table::rleid()
    示例数据:

    set.seed(123)
    df=data.frame(derv=rnorm(18),Date=as.Date(c(1,2,3,4,6,7,9,11,12,13,14,15,18,19,20,21,23,24),origin="2008-01-01"))
    

    创建一个带有索引的列,以便选择不超过所选日期前 10 天。

    library(dplyr)
    library(data.table)
    df %>%
      filter(Date < "2008-01-19") %>%
      mutate(id = rleid(Date)) %>%
      filter(id > (max(id)-10)) %>%
      ungroup() %>%
      select(derv,Date)
    
             derv       Date
    1  -1.0678237 2008-01-04
    2  -0.2179749 2008-01-05
    3  -1.0260044 2008-01-07
    4  -0.7288912 2008-01-08
    5  -0.6250393 2008-01-10
    6  -1.6866933 2008-01-12
    7   0.8377870 2008-01-13
    8   0.1533731 2008-01-14
    9  -1.1381369 2008-01-15
    10  1.2538149 2008-01-16
    

    编辑: Procrastinatus Maximus 的解决方案更短,只需要 dplyr

    df %>% filter(Date < "2008-01-19") %>% filter(row_number() > (max(row_number())-10))
    

    这给出了相同的输出。

    【讨论】:

    • 你也可以使用id = row_number() 代替rleid ;-)
    • 我认为只需两次调用filter 就足够了:df %&gt;% filter(Date &lt; "2008-01-19") %&gt;% filter(row_number() &gt; (max(row_number())-10))
    • @ProcrastinatusMaximus:你说得对,我没有想到row_number,这只是一个更好的解决方案。
    【解决方案2】:

    所以这个问题的答案实际上取决于你的日期是如何存储在 R 中的。但是让我们假设 ISO 8601,这就是根据你的代码的样子。

    所以首先让我们制作一些数据。

        mydates <- as.Date("2007-06-22")
        mydates<-c(mydates[1]+1:11, mydates[1]+14:19)
    
        StockPrice<-c(1:17)
    
        df<-data.frame(mydates,StockPrice)
    

    然后指定感兴趣的日期,如@stats_guy

        dateofinterest<-as.Date("2007-07-11")
    

    我会说使用子集,然后从您的日期中减去 11,因为它已经采用该格式。

        foo<-subset(df, mydates<dateofinterest & mydates>(dateofinterest-11))
    

    那么你会有一个不错的 10 天跨度,但我不确定你是否想要 10 个交易日?或者只是连续 10 天,即使这意味着您的价格列表可能

    假设您实际上是在寻找 10 个交易日。只是在这里成为魔鬼的拥护者,您可以假设没有交易的时间不会超过 10 天。因此,我们会在您感兴趣的日期前 20 天返回。

        foo<-subset(df, mydates<dateofinterest & mydates>(dateofinterest-20))
    

    然后我们使用if 语句检查您的数据子集,看看其中是否有超过 10 个交易日。如果有超过 10 行,那么您的天数太多了。我们只是将子集数据foo 从底部(最新日期)开始修剪到正确的长度,然后从那里开始计数 9 个条目。现在您在一个整洁的数据集中有十个交易日。

        if (nrow(foo)>10){
        foo<-foo[(nrow(foo)-9):(nrow(foo)),]
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-04
      • 1970-01-01
      • 2021-05-16
      • 2019-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-18
      相关资源
      最近更新 更多