2011-04-11 40 views
3

我有每小时记录的天气数据和每4小时记录的位置数据(X,Y)。我想知道位置X,Y的温度。天气数据并不完全相同。因此,我已经为每个位置编写了此循环,以扫描日期/时间中寻找“最接近”的天气数据并从该时间提取数据。问题在于我编写它的方式,对于位置#2,它扫描天气数据,但不会分配给位置#1的最近时间信息。说地点#1 & 2是在10分钟内在下午6点和6点10分,最近的天气时间是下午6点。我无法让它在下午6点允许天气数据作为选项。我有点像这样设置它,因为我的位置数据集中有200个位置(比如说3个月),我不希望它从时间0开始从天气数据开始,当我知道最近的天气数据只是为最后一个位置,这也恰好是该数据集的3个月。以下是一些示例数据和我的代码。我不知道这是否有道理。基于R中的移动时间窗口加入数据

<h6>####Location data</h6> 

<p>X Y DateTime <br /> 
1 2 4/2/2003 18:01:01 
3 2 4/4/2003 17:01:33 
2 3 4/6/2003 16:03:07 
5 6 4/8/2003 15:03:08 
3 7 4/10/2003 14:03:06 
4 5 4/2/2003 13:02:00 
4 5 4/4/2003 12:14:43 
4 3 4/6/2003 11:00:56 
3 5 4/8/2003 10:02:06</p> 

<h2>2 4 4/10/2003 9:02:19</h2> 

<p>Weather Data 
DateTime  WndSp WndDir Hgt 
4/2/2003 17:41:00 8.17 102.86 3462.43 
4/2/2003 20:00:00 6.70 106.00 17661.00 
4/2/2003 10:41:00 6.18 106.00 22000.00 
4/2/2003 11:41:00 5.78 106.00 22000.00 
4/2/2003 12:41:00 5.48 104.00 22000.00 
4/4/2003 17:53:00 7.96 104.29 6541.00 
4/4/2003 20:53:00 6.60 106.00 22000.00 
4/4/2003 19:41:00 7.82 105.00 7555.00 
4/4/2003 7:41:00 6.62 105.00 14767.50 
4/4/2003 8:41:00 6.70 106.00 17661.00 
4/4/2003 9:41:00 6.60 106.00 22000.00 
4/5/2003 20:41:00 7.38 106.67 11156.67 
4/6/2003 18:07:00 7.82 105.00 7555.00 
4/6/2003 21:53:00 6.18 106.00 22000.00 
4/6/2003 21:41:00 6.62 105.00 14767.50 
4/6/2003 4:41:00 7.96 104.29 6541.00 
4/6/2003 5:41:00 7.82 105.00 7555.00 
4/6/2003 6:41:00 7.38 106.67 11156.67 
4/8/2003 18:53:00 7.38 106.67 11156.67 
4/8/2003 22:53:00 5.78 106.00 22000.00 
4/8/2003 1:41:00 5.78 106.00 22000.00 
4/8/2003 2:41:00 5.48 104.00 22000.00 
4/8/2003 3:41:00 8.17 102.86 3462.43 
4/10/2003 19:53:00 6.62 105.00 14767.50 
4/10/2003 23:53:00 5.48 104.00 22000.00 
4/10/2003 22:41:00 6.70 106.00 17661.00 
4/10/2003 23:41:00 6.60 106.00 22000.00 
4/10/2003 0:41:00 6.18 106.00 22000.00 
4/11/2003 17:41:00 8.17 102.86 3462.43</p> 

<h2>4/12/2003 18:41:00 7.96 104.29 6541.0</h2> 

weathrow = 1 
for (i in 1:nrow(SortLoc)) { 
    t = 0 
    while (t < 1) { 
     timedif1 = difftime(SortLoc$DateTime[i], SortWeath$DateTime[weathrow], units="auto") 
     timedif2 = difftime(SortLoc$DateTime[i], SortWeath$DateTime[weathrow+1], units="auto") 
     if (timedif2 < 0) { 
      if (abs(timedif1) < abs(timedif2)) { 
       SortLoc$WndSp[i]=SortWeath$WndSp[weathrow] 
       SortLoc$WndDir[i]=SortWeath$WndDir[weathrow] 
       SortLoc$Hgt[i]=SortWeath$Hgt[weathrow] 
      } else { 
       SortLoc$WndSp[i]=SortWeath$WndSp[weathrow+1] 
       SortLoc$WndDir[i]=SortWeath$WndDir[weathrow+1] 
       SortLoc$Hgt[i]=SortWeath$Hgt[weathrow+1] 
      } 
      t = 1 
     } 
     if (abs(SortLoc$DateTime[i] - SortLoc$DateTime[i+1] < 50)) { 
      weathrow=weathrow 
     } else { 
      weathrow = weathrow+1 
      #if(weathrow = nrow(SortWeath)){t=1} 
     } 
    } #end while 
} 
+0

如果这是一个R问题,您能否提供一些易于使用的R格式的示例数据?即输入(对象)一小部分将会执行。 – 2011-04-12 04:39:51

+0

R代码上方有一小组数据。我不确定当我在学习时,输入(对象)意味着什么。 – Kerry 2011-04-12 16:33:14

+0

如果将一个对象(变量)放入dput(object),它将输出其他人可用来复制和粘贴部分数据的内容。 – 2011-04-12 20:56:12

回答

1

你可以使用findInterval功能找到最近的值:

# example data: 
x <- rnorm(120000) 
y <- rnorm(71000) 
y <- sort(y) # second vector must be sorted 
id <- findInterval(x, y, all.inside=TRUE) # finds position of last y smaller then x 
id_min <- ifelse(abs(x-y[id])<abs(x-y[id+1]), id, id+1) # to find nearest 

在你的情况可能需要一些as.numeric

# assumed that SortWeath is sorted, if not then SortWeath <- SortWeath[order(SortWeath$DateTime),] 
x <- as.numeric(SortLoc$DateTime) 
y <- as.numeric(SortWeath$DateTime) 
id <- findInterval(x, y, all.inside=TRUE) 
id_min <- ifelse(abs(x-y[id])<abs(x-y[id+1]), id, id+1) 
SortLoc$WndSp <- SortWeath$WndSp[id_min] 
SortLoc$WndDir <- SortWeath$WndDir[id_min] 
SortLoc$Hgt <- SortWeath$Hgt[id_min] 

一些另外:你应该从来没有,绝对较新的值在for循环添加到data.frame。检查这个比较:

N=1000 
x <- numeric(N) 
X <- data.frame(x=x) 
require(rbenchmark) 
benchmark(
    vector = {for (i in 1:N) x[i]<-1}, 
    data.frame = {for (i in 1:N) X$x[i]<-1} 
) 
#   test replications elapsed relative 
# 2 data.frame   100 4.32 22.74 
# 1  vector   100 0.19  1.00 

data.frame版本慢20倍以上,而如果更多的行它包含然后差异较大。

所以,如果你改变你的脚本,首先初始化结果向量:

tmp_WndSp <- tmp_WndDir <- tmp_Hg <- rep(NA, nrow(SortLoc)) 

环路

tmp_WndSp[i] <- SortWeath$WndSp[weathrow+1] 
# and so on... 

,并在年底再更新值(外循环)更新正确列:

SortLoc$WndSp <- tmp_WndSp 
SortLoc$WndDir <- tmp_WndDir 
SortLoc$Hgt <- tmp_Hgt 

它应该运行得更快。

+0

非常感谢你!这很好。并且不需要循环!现在要完全测试它! – Kerry 2011-04-14 00:27:40

1

下面是您可能使用的一种策略示例。这是一个接一个地经历天气时间,然后获取该位置与每个位置时间之间的差异的绝对值,然后获得时间上最低的差异。这解决了你的前瞻/回头问题。你的数据集看起来足够小,移动到一个半矢量化的解决方案应该是你需要的所有速度增益,但如果不是这样的话,它应该相对简单,只需在移动的窗口上添加一个仅在最后一个loc上通过+/- N个观察值的移动窗口。 match.index。

w <- as.POSIXct(strptime(c("4/2/2003 17:41:00","4/2/2003 20:00:00","4/2/2003 10:41:00","4/2/2003 11:41:00","4/2/2003 12:41:00"),format="%m/%d/%Y %H:%M:%S")) 
l <- as.POSIXct(strptime(c("4/2/2003 18:01:01","4/2/2003 17:01:33","4/2/2003 16:03:07","4/2/2003 15:03:08","4/2/2003 14:03:06","4/2/2003 13:02:00"),format="%m/%d/%Y %H:%M:%S")) 

window.size <- 5 

findClosest <- function(w.i,l) { 
    which.min(abs(w.i-l)) 
} 
makeWindow <- function(loc.match.index,i,window.size,n) { 
    win.max <- loc.match.index[i-1] + window.size 
    if(win.max > n) { 
     win.max <- n 
    } 
    win.min <- loc.match.index[i-1] - window.size 
    if(win.min < 1) { 
     win.min <- 1 
    } 
    return(seq(win.min,win.max)) 
} 

loc.match.index <- integer() 
n <- length(w) 
# Initialize on whole vector 
i <- 1 
loc.match.index[i] <- findClosest(w[i],l) 
# Continue on window 
for(i in seq(2,n)) { 
    wndw <- makeWindow(loc.match.index,i,window.size,n) 
    loc.match.index[i] <- findClosest(w[i],l[wndw]) 
    # Add the start of the window back to the index that was returned 
    loc.match.index[i] <- loc.match.index[i] + min(wndw)-1 
} 
> loc.match.index 
[1] 1 1 5 5 5 

还有可能会更高效这里的区域,但这应该尽快合理地考虑到的比较矢量和窗口可以调整。

+0

因此,我的数据集是120,000个地点,我的天气已经编译了5年,因此有71,000个天气数据。我以前写过这个脚本去做我认为你已经描述过的内容,但是需要8天的时间来处理和捆绑1台电脑来完成它。对于第1点,我计算了每个天气数据的日期/时间差异(71,000差异),然后找到最小值。现在做那120,000次。因此,一个窗口的想法。我不需要重新计算,也不需要一直搜索到最后。所以,你在窗口上的建议......如果你能解释一下更多一点? – Kerry 2011-04-12 16:31:11

+0

我试着运行您提供的更多天气数据的小脚本,并提出一个错误,指出data.frames需要具有相同的大小。在我目前的尝试中,天气点多于地点,但在最终版本中,会有比天气更多的地点。无论哪种方式... – Kerry 2011-04-12 16:39:18

+0

@Kerry:为您添加了一个窗口。 – 2011-04-13 04:28:35