【问题标题】:Searching Lists in R based on closest date [duplicate]根据最接近的日期搜索R中的列表[重复]
【发布时间】:2013-06-18 18:03:51
【问题描述】:

目前正在尝试编写一些可以从小于日期 X 的有序列表中返回最后一个日期。

现在我有这个:它获取日期列表,并获取我们将要进行搜索的那一天的索引以及我们想要返回多少日期的范围。

之后,它会检查日期是否存在(例如 2 月 30 日)。如果日期不存在,它会将日期减 1,然后再次应用过滤器(否则它会尝试从 NA 中减去 1 天并失败)。

library(lubridate)
getDate <- function(dates,day,range){
    if(range == 'single')
        {return (day-1)}

    z <- switch(range,
        single = days(1),
        month = days(30),
        month3 = months(3),
        month6 = months(6),
        year = years(1)
        )

    new_day <-(dates[day]-z)
    i <- 1
    while (is.na(new_day)){
        new_day <- dates[day] - days(i) - z 
    }
    ind<-which.min(abs (diff <-(new_day-dates)))

    if (diff[ind] < 0)
    {ind <- ind -1}

    return (ind[1])
}

虽然此功能有效,但问题在于速度效率。我感觉which.min(abs()) 远不是最快的,我想知道是否有更好的选择(除了编写我自己的搜索列表函数之外)。

stocks <- list(structure(list(sec = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), hour = c(0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L), mday = c(2L, 3L, 4L, 7L, 8L, 9L, 10L, 11L, 14L, 15L, 16L, 17L,
18L, 22L, 23L, 24L, 25L, 28L, 29L, 30L, 31L, 1L, 4L, 5L, 6L), mon = c(0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L,
1L, 1L, 1L), year = c(108L, 108L, 108L, 108L, 108L, 108L, 108L, 108L, 108L,
108L, 108L, 108L, 108L, 108L, 108L, 108L, 108L, 108L, 108L, 108L, 108L, 108L,
108L, 108L, 108L), wday = c(3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L,
2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L), yday = c(1L, 2L, 3L, 6L, 7L,
8L, 9L, 10L, 13L, 14L, 15L, 16L, 17L, 21L, 22L, 23L, 24L, 27L, 28L, 29L, 30L,
31L, 34L, 35L, 36L), isdst = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L,
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c("sec", "min",
"hour", "mday", "mon", "year", "wday", "yday", "isdst"), tzone = "UTC",
class = c("POSIXlt", "POSIXt")))

old_pos <- getDate(stocks[[1]],21,"month") #should return 0
old_pos <- getDate(stocks[[1]],22,"month") #should return 1

这不返回向量,也不返回日期,只返回一个索引,主要问题不在于工作(它确实如此),而是优化它。

该值稍后会在另一个函数中使用,一个可能的加速方法是首先将所有旧索引与新索引匹配,然后将其作为另一个列表返回。但是不确定它是否会提供任何加速。

【问题讨论】:

  • 请提供一些可重复的数据进行测试。
  • pastebin.com/sDXMSft6pastebin.com/vLVvwjHd(作为股票传递的唯一值是股票[[1]])
  • 请提供dput(head(stocks[[1]],20)) 的输出以及我们应该如何调用您的getDate 函数的示例,而不是粘贴指向打印数据的链接。那么您的问题将包含一个最小值,reproducible example
  • @Gray_Hound 您可以从我的回答中得到启发,创建一个具有预期结果的可重复示例。创建一个好的示例通常是解决问题的一半。
  • 我同意其他人的观点,他们鼓励您改进提问方式。现在出现的问题中有太多不相关的代码和过多的数据。这不仅仅是将你拥有的任何东西倾倒在 SO 上的问题,而是提取它的肉并问这个问题。我在回答中回答了@agstudy 对您问题的重新表述。我怀疑也没有多少人愿意浏览你所介绍的内容。

标签: r list date search indexing


【解决方案1】:

使用@agstudy 的重新表述,包括sDatex.Date

data.table

我们可以像这样在data.table中进行计算,其中第一列显示sDate中的原始日期,第二列是对应的x.Date日期:

> library(data.table)
> data.table(date = x.Date, x.Date, key = "date")[J(sDate),, roll = TRUE]
         date     x.Date
1: 2003-02-03 2003-02-02
2: 2003-02-12 2003-02-10
3: 2003-02-16 2003-02-15

sqldf 使用 sqldf 如下:

> library(sqldf)
> sDateDF <- data.frame(sDate = sDate)
> xDateDF <- data.frame(xDate = x.Date)
> 
> sqldf("select s.sdate sDate, max(x.xdate) xDate 
+   from sDateDF s join xDateDF x on x.xDate <= s.sDate 
+   group by s.sDate")
       sDate      xDate
1 2003-02-03 2003-02-02
2 2003-02-12 2003-02-10
3 2003-02-16 2003-02-15

动物园

使用 zoo,我们创建了两个 zoo 系列,合并它们并像这样使用 na.locf。结果是每个sDate 对应的x.Date(即上述任一解决方案中的第二列):

> library(zoo)
>
> zx <- zoo(seq_along(x.Date), x.Date)
> zs <- zoo(seq_along(sDate), sDate)
> x.Date[na.locf(merge(zx, zs))[sDate, "zx"]]
[1] "2003-02-02" "2003-02-10" "2003-02-15"

【讨论】:

    【解决方案2】:

    如果我知道你有一个日期向量,例如:

    x.Date <- as.Date("2003-02-01") + c(1, 3, 7, 9, 14,20) 
    "2003-02-02" "2003-02-04" "2003-02-08" "2003-02-10" "2003-02-15" "2003-02-21"
    

    并给出一个日期向量,例如:

    sDate <- as.Date("2003-02-01") + c(2,11,15)
    

    您尝试在 x.Date 中获取更接近此捐赠日期但小于此日期的日期:

     lapply(sDate,function(x)max(x.Date[x.Date-x <=0]))
    [[1]]
    [1] "2003-02-02"
    
    [[2]]
    [1] "2003-02-10"
    
    [[3]]
    [1] "2003-02-15"
    

    【讨论】:

    • 是的,只有特定的事情是 sDate 是列表中的日期之一 - 固定时间间隔之一。
    • @Gray_Hound 我编辑我的答案。 sDate 现在是日期列表。
    • @agstudy is.list(sDate) 不是 TRUE
    • @Roland 是的,但我不明白你的意思......你的意思是我lapply(as.list(sDate),...)
    • @agstudy is.vector(unclass(sDate)) == TRUE。它是一个带有属性的向量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 2013-08-01
    • 2022-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多