當處理密集型計算總是有意義考慮Rcpp
包。如果你想獲得與歐氏距離的距離矩陣快,可以實現相應的功能Rcpp
:
library(Rcpp)
library(inline)
# Rcpp function for euclidean distance
fastdist <- cxxfunction(signature(x="matrix", y="matrix"), plugin="Rcpp",
body='
Rcpp::NumericMatrix dx(x);
Rcpp::NumericMatrix dy(y);
const int N = dx.nrow();
const int M = dy.nrow();
Rcpp::NumericMatrix res(N, M);
for(int i=0; i<N; i++){
for(int j=0; j<M; j++){
res(i,j) = sqrt(sum((dx(i,_)-dy(j,_))*(dx(i,_)-dy(j,_))));
}
}
return res;
')
它採用Rcpp
句法sugar
爲了讓代碼更緊湊和可讀性。但是,有時最好使用包裝函數來檢查類型,強制等。這不是必需的 - 您可以直接撥打fastdist
。但是,無論如何,包裝可以看起來像這樣:
# Wrapper R function
fast.dist <- function(x, y){
stopifnot(class(x) %in% c("data.frame","matrix") &
class(y) %in% c("data.frame","matrix") &
ncol(x)==ncol(y))
fastdist(as.matrix(x), as.matrix(y))
}
現在我們可以轉向文學的例子。
library(dtw)
# EXAMPLE 1
x<- cbind(1:10,1)
y<- cbind(11:15,2)
# Check results
all.equal(fast.dist(x,y), dist(x,y,method="euclidean"), check.attributes=F)
# [1] "target is matrix, current is crossdist"
all.equal(fast.dist(x,y), matrix(dist(x,y,method="euclidean"), ncol=nrow(y)))
# [1] TRUE
注意,那dist
返回結果crossdist
類的。所以,爲了比較,它應該被強制爲matrix
。
現在你的首要問題 - 我們首先生成數據:
# EXAMPLE 2
set.seed(1234)
N <- 100
inDf <- data.frame(matrix(rnorm(6*N), ncol = 6))
colnames(inDf) <- c('var1t1','var2t1','var1t2','var2t2','var1t3','var2t3')
# Extracting variables
var1 <- inDf[,c("var1t1","var1t2","var1t3")]
var2 <- inDf[,c("var2t1","var2t2","var2t3")]
我不能完全肯定你的數據結構,但在任何情況下,你可以根據自己的需要隨時準備變量。
比較和基準:
library(rbenchmark)
all.equal(fast.dist(var1,var2), matrix(dist(var1,var2), ncol=N))
# [1] TRUE
benchmark(fast.dist(var1,var2), dist(var1,var2), order="relative")[,1:4]
# test replications elapsed relative
# 1 fast.dist(var1, var2) 100 0.081 1.000
# 2 dist(var1, var2) 100 0.246 3.037
fast.dist
比dist
在這種情況下更快的大致3倍。然而,雖然N
正在增長,相對加速將下降。
另請注意,如評論中所述,dtw
可以自行計算距離矩陣。不過,預先計算距離矩陣會更有效率。請參見下面的快速測試:
cxdist <- fast.dist(var1,var2)
benchmark(dtw(cxdist)$distance, dtw(var1,var2)$distance, order="relative")[,1:4]
# test replications elapsed relative
# 1 dtw(cxdist)$distance 100 0.476 1.000
# 2 dtw(var1, var2)$distance 100 0.736 1.546
另外,如果你只關心$distance
你可以通過distance.only=T
到dtw()
- 它提供了一些加速。
因此,您需要高效計算var1和var2之間的距離矩陣(euclidean)(兩者都是相同長度的三維數組)?即在'x < - inDf [,c(「var1t1」,「var1t2」,「var1t3」)]'和'y < - inDf [,c(「var2t1」,「var2t2」,「var2t3」)]''之間? – redmode
你能否澄清一下'inDf'如何與你的第一個例子相關?是'var1t1''x'和'var2t1''y',然後再重複其他兩個時間段?你是否正在計算每個時間段內每對變量的「dtw」距離?這些東西與圖像有什麼關係?另外,它看起來像'dtw'計算'dist'本身,所以你不需要那一步。 – BrodieG
第一個和第二個示例之間的差異是每個樣本測量的變量數量。首先,x和y都是隨時間變化的同一個唯一變量的時間序列。第二,每個x由兩個變量表徵,兩個時間序列。希望它更清晰 – WAF