【问题标题】:compute angle between moving vectors计算移动向量之间的角度
【发布时间】:2014-03-11 19:29:05
【问题描述】:

我有一个如下所示的数据框:

    structure(list(K = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), T = c(1L, 2L, 3L, 4L, 5L, 6L, 
7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 
20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 
33L, 34L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 
13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 
26L, 27L, 28L, 29L, 30L, 31L, 32L), X = c(26.892, 23.904, 23.904, 
23.904, 23.904, 23.904, 23.904, 23.904, 23.904, 20.916, 20.916, 
20.916, 20.916, 20.916, 20.916, 20.916, 20.916, 20.916, 20.916, 
20.916, 29.88, 20.916, 14.94, 8.964, 8.964, 5.976, 5.976, 5.976, 
5.976, 5.976, 5.976, 5.976, 5.976, 5.976, 857.56, 860.54, 857.56, 
857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 
857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 
857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 857.56, 
857.56, 857.56, 857.56, 857.56, 857.56), Y = c(167.33, 167.33, 
164.34, 164.34, 164.34, 164.34, 164.34, 164.34, 164.34, 143.42, 
143.42, 143.42, 143.42, 143.42, 143.42, 143.42, 143.42, 143.42, 
143.42, 143.42, 176.29, 182.27, 185.26, 188.24, 188.24, 188.24, 
188.24, 188.24, 188.24, 188.24, 188.24, 188.24, 188.24, 188.24, 
256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 
256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 
256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 
256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97, 256.97
), V = c(2.1128, 1.494, 0, 0, 0, 0, 0, 10.564, 10.564, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 17.034, 19.422, 8.7114, 6.6814, 3.3407, 
1.494, 1.494, 0, 0, 0, 0, 0, 0, 0, 0, 20.1, 0, 1.494, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 1.494, 1.494), P = c(-135, -90, 0, 0, 0, 0, 0, -98.13, 
-98.13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74.745, 90, 149.04, 153.43, 
153.43, 180, 180, 0, 0, 0, 0, 0, 0, 0, 0, 41.987, 0, 180, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 90, 90)), .Names = c("K", "T", "X", "Y", "V", 
"P"), row.names = c(NA, 66L), class = "data.frame")

因为我有 X、Y 位置,所以要制作两个向量,我应该考虑三个 X、Y 位置来计算一个角度。我知道:

theta <- acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)) ) )

来自另一个 stackoverflow 答案 (Angle between two vectors in R)。

我还需要计算每个 T 的角度作为每个 K 中的一个因子。我知道我可以在其中使用 split

但是如何定义计算角度的向量和角度本身的函数呢?谢谢。

在这张图上,我有一个运动的 X、Y 位置,我需要计算运动的角度。我希望这会有所帮助。还应注意,第一个和最后一个 X、Y 位置没有可能的角度。谢谢

【问题讨论】:

  • 感谢您以一种很好的方式分享数据,但我仍然对您想要的内容感到困惑。你说你有 3 个 (x,y) 位置,所以我假设 (K,T)、(X,Y) 和 (V,P)。 (这实际上看起来不对,但我不知道还能怎么想。)哪个是角的顶点?你如何理解“每 K 作为一个因素”?在您的示例中,所有 K 值都是 1。
  • 这只是我的数据的头部。我有多个K。我没有固定的顶点,我有一个移动的顶点。 K,T,X,Y,V,P 不是我的 X,Y 位置,它们是我的列。只应使用 X、Y 位置进行计算。
  • 好的,那么,在数据的头部,您想根据行数计算哪些角度?某种运行角度,第 1,2,3 行中 (X,Y) 之间的角度,然后是 2,3,4,然后是 3,4,5? (X,Y) 的每个组合? T、V、P 列对这个问题有影响吗?
  • 是的,你是对的。 T,V,P 无关紧要。它们只是我数据框中的变量。
  • 您的问题仍然有点令人困惑。也许,为了澄清,您可以附上一张图表,说明您尝试做什么以及预期结果的示例。

标签: r trigonometry angle


【解决方案1】:

所以您的数据框有 6 行。前 3 组 (X,Y) 定义了一个直角 (th=90)。接下来的三组 (X,Y),第 4-6 行,与第 3 行相同。所以这些点彼此重叠,没有角度。此外,K 只有一个值,因此很难通过 K 来证明聚合。

不过,这似乎可行:

df <- rbind(df,df,df)     # replicate the original data 3 times
df$K <- rep(1:3,each=6)   # K = 1, 2, 3
# theta in degrees
theta <- function(a,b)(180/pi)*(acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)))))
# this returns a vector of the angles between successive line segmeents
get.angles <- function(df.split){
  dx<- diff(df.split$X)
  dy<- diff(df.split$Y)
  sapply(1:(nrow(df.split)-2),function(i){
    a <- c(dx[i],dy[i])
    b <- c(dx[i+1],dy[i+1])
    theta(a,b)
  }) 
}
# this calls get.angles(...) for each subset of df, based on K
sapply(split(df,df$K),get.angles)
#        1   2   3
# [1,]  90  90  90
# [2,] NaN NaN NaN
# [3,] NaN NaN NaN
# [4,] NaN NaN NaN

EDIT(对 OP 的附加数据和 cmets 的响应)

因此,随着对问题的相当大的改变,这个重新设计的解决方案似乎有效。使用您对df 的新定义,

theta <- function(a,b)(180/pi)*(acos(sum(a*b)/(sqrt(sum(a*a))*sqrt(sum(b*b)))))
get.angles <- function(df.split){
  dx<- diff(df.split$X)
  dy<- diff(df.split$Y)
  stops <- which(dx^2+dy^2==0)
  dx<- dx[-stops]
  dy<- dy[-stops]
  df<- df.split[-(stops+1),]
  sapply(1:(length(dx)-1),function(i){
    a <- c(dx[i],dy[i])
    b <- c(dx[i+1],dy[i+1])
    return(cbind(df[i+1,],angle=180-theta(a,b)))
  })
}
result <- t(do.call(cbind,lapply(split(df,df$K),get.angles)))
result
#      K T  X      Y      V      P      angle   
# [1,] 1 2  23.904 167.33 1.494  -90    90      
# [2,] 1 3  23.904 164.34 0      0      171.8714
# [3,] 1 10 20.916 143.42 0      0      7.125665
# [4,] 1 21 29.88  176.29 8.7114 149.04 108.4535
# [5,] 1 22 20.916 182.27 6.6814 153.43 172.8726
# [6,] 1 23 14.94  185.26 3.3407 153.43 179.9233
# [7,] 1 24 8.964  188.24 1.494  180    153.4963
# [8,] 2 2  860.54 256.97 1.494  180    0       

此版本会删除 dx2+dy2=0(长度为 0 的线)的点,即同一位置的重复点,并计算剩余点的角度。请注意,我使用的是“内部”角度(

library(ggplot2)
ggplot(df[df$K==1,],aes(x=X,y=Y))+
  geom_path()+geom_point(colour="red")+coord_fixed()

注意coord_fixed() 的使用。这迫使纵横比为 1:1。否则角度会失真。

【讨论】:

  • 你好,有一个问题是,如果我有运动,然后没有运动,然后又运动,即使有角度,它也将NaN作为角度。我会更新我的数据结构,这样你就可以明白我的意思了..
  • 我有一个愚蠢的问题。我检查了整个 X、Y 位置的值,我做了r=merge(df,result[, c (1:2, 7)], by=c("K", "T"), all=TRUE)。首先,我注意到在 K=1、T=24 时,我的 X、Y 值发生了变化,但角度没有变化。第二,angle=180-theta(a,b) 是内角吧?我怎样才能改变它,使角度可以从 -180 到 180?因为我也想在上下移动之间有一条清晰的界限。谢谢!
  • 首先,从T=23到T=24有变化,但是之后没有,所以没看出问题。在图中,您可以看到 K=1 有 7 个角度,在results 中您可以看到 K=1 有 7 个角度。无论如何,原始设置将angle 与定义角度的三个点中的第一个 相关联。我在上面更新了这个以将角度与中间(顶点)点相关联。也许这更清楚。其次,是的,正如答案所述,这些是内角。如果你想知道运动是向上还是向下,你可以看看dy的值。
  • 对不起,我可能错过了。查看 dy 的值可能不是一个好主意,因为我有数千个 K。尽管计算内角是对的。再次感谢:)
【解决方案2】:

你可以用 'lapply` 包裹 split 来做到这一点:

getAngle <- function(X, Y) acos( sum(X*Y) / ( sqrt(sum(X * X)) * sqrt(sum(Y * Y)) ) )
lapply(split(df[, c("X", "Y")], f = list(df$K)), 
       FUN = function(x){ getAngle(x[, 1], x[, 2])})

# $`1`
#[1] 0.04074904

【讨论】:

  • 我收到一个错误:Error in x[, 1] : incorrect number of dimensions
  • aggregate 将数据框转换为向量,然后将其传递给FUN。我没有意识到这一点。我修复了它,使它使用 lapplysplit 并且实际工作(我得到 0.04)。
  • 我忘了补充说我也想要每个T 的角度。抱歉,我会解决这个问题。
  • f in split 可以是获得交互的因素列表。
  • 您好,我想我做错了。如果我在拆分中使用f = list(df$K, df$A),我会得到角度的所有 0 值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-20
  • 2011-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-23
  • 2019-10-30
相关资源
最近更新 更多