2013-06-21 53 views
1

目前嘗試寫一些會從一個有序列表小於日期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 

這不返回矢量,也不是迄今爲止,只有一個指標,主要問題不在於工作(其中它),但它的優化。

該值稍後在另一個函數中使用,一種可能的加速是首先將所有舊索引匹配到新索引,然後將其作爲另一個列表返回。但不知道它是否會提供任何加速。

+3

請提供用於測試的一些可再生的數據。 – Roland

+0

http://pastebin.com/sDXMSft6或 http:// pastebin。com/vLVvwjHd (唯一的值是以股票形式傳入股票[[1]]) –

+2

而不是粘貼到打印數據的鏈接,請提供'dput(head(stocks [[1]],20 ))和我們應該如何調用getDate函數的例子。那麼你的問題將包含一個最小的[可重現的例子](http://stackoverflow.com/q/5963269/271616)。 –

回答

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" 
+0

是的,只有特定的事情是sDate是列表中的日期之一 - 固定的時間間隔之一。 –

+0

@Gray_Hound我編輯我的答案。 sDate現在是日期列表。 – agstudy

+0

@agstudy'is.list(sDate)'不是'TRUE'。 – Roland

3

使用@ 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 

動物園

使用動物園,我們創建了兩個動物園系列,進行合併使用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"