【问题标题】:Subset dataframe where date is within x days of a vector of dates in R子集数据框,其中日期在 R 中日期向量的 x 天内
【发布时间】:2013-10-14 06:38:31
【问题描述】:

我有一个日期向量,例如

dates <- c('2013-01-01', '2013-04-02', '2013-06-10', '2013-09-30')

还有一个包含日期列的数据框,例如

df <- data.frame(
                'date' = c('2013-01-04', '2013-01-22', '2013-10-01', '2013-10-10'),
                'a'    = c(1,2,3,4),
                'b'    = c('a', 'b', 'c', 'd')
                )

我想对数据框进行子集化,使其仅包含日期在“日期”向量中的任何日期之后不到 5 天的行。

即初始数据框如下所示

date       a b 
2013-01-04 1 a
2013-01-22 2 b
2013-10-01 3 c
2013-10-10 4 d

查询后,我只会留下第一行和第三行(因为 2013-01-04 在 2013-01-01 的 5 天内,而 2013-10-01 在 2013-09-30 的 5 天内)

有人知道最好的方法吗?

提前致谢

【问题讨论】:

  • 试试df$date %in% dates
  • @Roman,OP 正在寻找与日期相关的范围
  • @RicardoSaporta doh,高级时刻。

标签: r date dataframe subset


【解决方案1】:

使用data.table 滚动很容易(而且非常快):

library(data.table)
dt = data.table(df)

# convert to Date (or IDate) to have numbers instead of strings for dates
# also set the key for dates for the join
dt[, date := as.Date(date)]
dates = data.table(date = as.Date(dates), key = 'date')

# join with a roll of 5 days, throwing out dates that don't match
dates[dt, roll = 5, nomatch = 0]
#         date a b
#1: 2013-01-04 1 a
#2: 2013-10-01 3 c

【讨论】:

  • 谢谢,我已经开始更多地使用数据表,并且知道它们有多好,所以这看起来可能是最好和最快的方法,但是准确地复制你的代码(和我的集合上面)为我返回一个空数据表......知道我可能做错了什么吗?
  • @user1165199 你得到一个空的data.table 与OP 中的例子?这很奇怪——也许重新启动你的会话以防你覆盖了 smth?
  • 它仍然是空的,但是当我将滚动增加到很大的东西(10000000000)时,它会返回所有行。难道我的日期被存储为日期时间或其他东西,它增加了 5 秒而不是 5 天?
  • @user1165199 as.Date 应该将任何内容转换为日期,它没有时间,我建议 dput'ing 数据的一小部分(或更具有代表性的样本,因为它听起来像OP不是)。你也可以试试as.IDate 看看是否有什么不同。
  • 我已经安装了最新版本的data.table,现在可以正常使用了,不知道之前是什么问题...感谢您的帮助!
【解决方案2】:

分为几个步骤:

# Rows Selected: Iterate over each row in the DF, 
#   and check if its `date` value is within 5 from any value in the `dates` vector
rows <- sapply(df$date, function(x) any( abs(x-dates) <=  5))

# Use that result to subset your data.frame
df[rows, ]

#         date a b
# 1 2013-01-04 1 a
# 3 2013-10-01 3 c

重要的是,确保您的日期值是实际的Dates,而不是看起来像日期的characters

dates <- as.Date(dates)
df$date <- as.Date(df$date)

【讨论】:

    【解决方案3】:

    首先确保df$date 是上课日期。那么:

    df[df$date %in% sapply(dates, function(x) x:(x+5)),]
    
            date a b
    1 2013-01-04 1 a
    3 2013-10-01 3 c
    

    出于某种原因,我觉得这可能是一种更合适的方法:

     df[df$date %in% mapply(`:`, from=dates, to=dates+5),]
    

    【讨论】:

    • 只使用abs ;) 少很多搜索和迭代
    • @RicardoSaporta 我认为 OP 只要求了 5 天后
    • 公平地说,OP 对他想要的范围有两种不同的措辞,这使得它不清楚。无论如何,@RicardoSaporta 从df$dates 中直接减去dates 的方法在大多数情况下应该会做得更好——尽管我很想知道这种方法是否/何时会更好。
    • 就个人而言,我更喜欢@eddi 的方法,但我当然会:) 但是我确实这样做,我认为让用户了解正在发生的事情以及如何实现这一点很重要
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 2021-05-06
    • 1970-01-01
    相关资源
    最近更新 更多