我有每小时记录的天气数据,以及每4小时记录一次的位置数据(X,Y)。我想知道X,Y位置的温度。天气数据并非完全同时出现。所以,我已经为每个位置编写了这个循环来扫描天气数据,寻找日期/时间中的“最接近”并从那个时间提取数据。问题是我写它的方式,对于位置#2,它扫描天气数据但不允许分配为位置#1分配的最近时间信息。说位置#1& 2点在下午6点和下午6点10分钟内拍摄,最近的天气时间是下午6点。我无法让它在下午6点允许天气数据作为选项。我有点像这样设置,因为200个位置进入我的位置数据集(比如3个月),我不希望它从时间0开始从天气数据,当我知道最接近的天气数据是刚刚计算的最后一个位置,恰好是该数据集的3个月。下面是一些示例数据和我的代码。我不知道这是否有意义。
<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 :(得分:1)
以下是您可能使用的一种策略的示例。这将逐个经历天气时间,然后获取该时间与每个位置时间之间差异的绝对值,然后获取最低时间差异。这解决了你的前瞻/回顾问题。您的数据集似乎足够小,以至于移动到半矢量化解决方案应该是您需要的所有速度增益,但如果不是,则添加到移动窗口上应该相对简单,该窗口仅在最后一个位置周围传递一些+/- 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
这里仍有一些区域可以提高效率,但考虑到比较是矢量化的,窗口可以调整,这应该合理快速。
答案 1 :(得分: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
它应该运行得更快。