我有一个如下所示的数据框:
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位置没有可能的角度。感谢
答案 0 :(得分: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
编辑(对OP的其他数据和评论的回应)
因此,随着问题的相当大的改变,这种重新设计的解决方案似乎有效。使用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
此版本删除了dx 2 + dy 2 = 0(长度为0的行)的点,换句话说,在同一位置重复的点,并计算其余点的角度。请注意,我正在使用“内部”角度(&lt; 180)。最后,我们绘制数据以显示这些确实是正确的角度:
library(ggplot2)
ggplot(df[df$K==1,],aes(x=X,y=Y))+
geom_path()+geom_point(colour="red")+coord_fixed()
请注意coord_fixed()
的使用。这迫使纵横比为1:1。否则角度会扭曲。
答案 1 :(得分:0)
您可以使用&#39; 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