2016-10-04 42 views
1

我只是試圖計算我的x,y,z數據框與參考矢量之間的相對角度。到目前爲止,我使用dplyr來分組事物並應用我的angle函數來獲取相對角度。然而,即使我在這裏提供的虛擬數據也很慢。事情比較慢,「dplyr」有沒有更快的方法?

set.seed(12345) 

x <- replicate(1,c(replicate(1000,rnorm(50,0,0.01)))) 
y <- replicate(1,c(replicate(1000,rnorm(50,0,0.01)))) 
z <- replicate(1,c(replicate(1000,rnorm(50,0.9,0.01)))) 
ref_vector <- data.frame(ref_x=rep(0,100),ref_y=rep(0,100),ref_z=rep(1,100)) 
set <- rep(seq(1,1000),each=50) 

data_rep <- data.frame(x,y,z,ref_vector,set) 

>

head(data_rep) 
#   x   y   z ref_x ref_y ref_z set 
# 1 0.005855288 -0.015472796 0.9059337  0  0  1 1 
# 2 0.007094660 -0.013354359 0.9040137  0  0  1 1 
# 3 -0.001093033 -0.014661486 0.9047502  0  0  1 1 
# 4 -0.004534972 -0.002764655 0.9070553  0  0  1 1 
# 5 0.006058875 -0.008339952 0.8926551  0  0  1 1 
# 6 -0.018179560 -0.008412400 0.9055541  0  0  1 1 

我定義與此angle函數的兩個向量之間的角度,

angle <- function(x,y){ 
    dot.prod <- x%*%y 
    norm.x <- norm(x,type="2") 
    norm.y <- norm(y,type="2") 
    theta <- acos(dot.prod/(norm.x * norm.y)) 
    as.numeric(theta) 
} 

然後讓這適用於我們data_rep

library(dplyr) 
system.time(df_angle <- data_rep%>% 
    rowwise()%>% 
    do(data.frame(.,angle_rad=angle(unlist(.[1:3]),unlist(.[4:6]))))%>% 
    group_by(set)%>% 
    mutate(angle=angle_rad*180/pi, mean_angle=mean(angle))) 

#  user system elapsed 
#  64.22 0.08 64.81 
# Warning message: 
# Grouping rowwise data frame strips rowwise nature 

正如你所看到的,這個過程大約需要1分鐘,我甚至沒有提供我所有的具有350000行的實際數據集,需要10分鐘來計算相對角度。

我不知道有什麼辦法可以加快這個過程。

謝謝!

+2

'橫行()'往往是很慢。如果可以的話,可以在'angle()'中找到需要計算的東西,這樣它就不需要在你的dplyr鏈中不存在。我認爲'angle()'中的問題是你計算了兩個矩陣(兩個'norm()')。如果不知何故,你可以採取不同的措施,那麼你應該沒問題。 –

回答

7

只需製作一個簡單的mutate聲明,而不是您的do(data.frame())聲部。這提高了性能相當多,因爲你再也不用爲每一行轉換成一個data.frame

system.time(df_angle2 <- data_rep%>% 
       rowwise() %>% 
       mutate(angle_rad=angle(x = c(x,y,z),y = c(ref_x,ref_y,ref_z))) %>% 
       group_by(set)%>% 
       mutate(angle=angle_rad*180/pi, mean_angle=mean(angle))) 

##  user  system  elapsed 
##  3.72  0.00  3.71 

all.equal(df_angle,df_angle2) 
## TRUE 
16

才發現自己的線性代數:

m1 = as.matrix(data_rep[, 1:3]) 
m2 = as.matrix(data_rep[, 4:6]) 

system.time({ 
    m1 = m1/sqrt(rowSums(m1^2)) 
    m2 = m2/sqrt(rowSums(m2^2)) 
    RESULT <- acos(rowSums(m1 * m2)) 
}) 
# user system elapsed 
# 0.004 0.001 0.006 
all.equal(df_angle$angle_rad, RESULT) 
# TRUE 
相關問題