" dplyr"有更快的方法吗?

时间:2016-10-04 09:00:07

标签: r data.table dplyr

我只是想计算我的x,y,z数据帧与参考向量之间的相对角度。到目前为止,我使用dplyr对事物进行分组并应用我的angle函数来获取相对角度。但是,即使是我在这里提供的虚拟数据,事情也很慢。

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)

&GT;

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 个答案:

答案 0 :(得分:21)

为自己发现线性代数:

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

答案 1 :(得分:7)

只需制作简单的0语句,而不是mutate部分。这样可以提高性能,因为您不再需要将每一行转换为do(data.frame())

data.frame