如何计算R中一系列样本中两条线向量之间的角度列表?

如何计算R中一系列样本中两条线向量之间的角度列表?,r,geometry,trigonometry,computational-geometry,R,Geometry,Trigonometry,Computational Geometry,我正在使用二维笛卡尔坐标(即地标)制作生物标本的几何形态测量数据集。我对该数据集感兴趣的一部分是生成重要地标之间的距离和地标向量之间的角度的数据框架,并在所有样本中使用同源坐标进行进一步比较。点之间的距离不是问题,但当我试图计算每个样本的角度时,我遇到了问题 data<-array(data=c(-0.2411,-0.0677,0.1147,0.0085,0.060183,-0.029954,0.012111,0.000462,-0.22509,-0.09437,0.09135,0.003

我正在使用二维笛卡尔坐标(即地标)制作生物标本的几何形态测量数据集。我对该数据集感兴趣的一部分是生成重要地标之间的距离和地标向量之间的角度的数据框架,并在所有样本中使用同源坐标进行进一步比较。点之间的距离不是问题,但当我试图计算每个样本的角度时,我遇到了问题

data<-array(data=c(-0.2411,-0.0677,0.1147,0.0085,0.060183,-0.029954,0.012111,0.000462,-0.22509,-0.09437,0.09135,0.00367,0.0764,-0.0202,-0.0182,-0.0045,-0.2223,-0.1001,0.0553,-0.0617,0.06122,-0.02366,0.00577,-0.01557),c(4,2,3))
我试图找到一种方法来计算一系列样本上代表相同角度的线向量之间的角度(向量描述了一个具有生物学意义的特征,该特征存在于我的数据集中的所有样本中)。我用来操作形态测量数据的R包将地标作为类
array()
的三维对象输出,其中行是地标,列是坐标的尺寸,第三维是样本。以下是样本数据中三个样本的地标坐标

, , Specimen1

         X         Y
1  -0.2411  0.060183
2  -0.0677 -0.029954
3   0.1147  0.012111
4   0.0085  0.000462

, , Specimen2

          X       Y
1  -0.22509  0.0764
2  -0.09437 -0.0202
3   0.09135 -0.0182
4   0.00367 -0.0045

, , Specimen3

         X        Y
1  -0.2223  0.06122
2  -0.1001 -0.02366
3   0.0553  0.00577
4  -0.0617 -0.01557
下面是一个可读数组,它复制了我作为前三个样本的输出而获得的数据

data<-array(data=c(-0.2411,-0.0677,0.1147,0.0085,0.060183,-0.029954,0.012111,0.000462,-0.22509,-0.09437,0.09135,0.00367,0.0764,-0.0202,-0.0182,-0.0045,-0.2223,-0.1001,0.0553,-0.0617,0.06122,-0.02366,0.00577,-0.01557),c(4,2,3))
然后以某种方式将其添加到数据帧中,使其看起来像这样:

          Distance Angle1 Angle2
Specimen1 100      146    100
Specimen2 100      152    100
Specimen3 100      135    100
Angle2的距离和值只是填充数字,以显示我试图实现的格式

我已经尝试在mathlib包中使用
angle()
函数,在Morpho包中使用
angle.calc()
函数。下面是我使用
angle()
函数计算角度的代码

vector1<-data[1,,]-data[2,,]
vector2<-data[3,,]-data[4,,]
angle(as.vector(vector1),as.vector(vector2),degree=TRUE)

vector1首先,给
2x3
矩阵命名
vector1
有点混乱。除此之外,您可以使用
matlib::angle
计算角度

library(matlib)
phi <- setNames(mapply(
    function(x1, x2) angle(x1, x2),
    as.data.frame(vector1), as.data.frame(vector2)),
    paste0("Specimen", 1:ncol(vector1)))
phi
#Specimen1 Specimen2 Specimen3
# 146.2674  152.4439  134.8753

首先,给一个
2x3
矩阵命名
vector1
有点混乱。除此之外,您可以使用
matlib::angle
计算角度

library(matlib)
phi <- setNames(mapply(
    function(x1, x2) angle(x1, x2),
    as.data.frame(vector1), as.data.frame(vector2)),
    paste0("Specimen", 1:ncol(vector1)))
phi
#Specimen1 Specimen2 Specimen3
# 146.2674  152.4439  134.8753

一般来说,您可能会发现首先以长/整齐的格式获取数据更简单。这使得分组和聚合更加容易,这是矢量化/映射操作真正发挥作用的地方

使用您提供的数据,有一种方法可以做到这一点:

library(matlib)
library(tidyverse)

n_specimen <- ncol(vector1)

data.frame(t(vector1)) %>%
  rename_all(~str_replace(., "X", "v1_")) %>%
  bind_cols(
    data.frame(t(vector2)) %>%
      rename_all(~str_replace(., "X", "v2_"))
    ) %>%
  mutate(specimen = paste0("Specimen", 1:n_specimen)) %>%
  pivot_longer(-specimen, names_to = "vector", values_to = "value") %>%
  separate(vector, into = c("vector", "ix"), sep = "_", remove = TRUE) %>%
  group_by(specimen) %>%
  summarise(angle = angle(value[vector == "v1"], value[vector == "v2"])) 

  specimen  angle
  <chr>     <dbl>
1 Specimen1  146.
2 Specimen2  152.
3 Specimen3  135.

每一列都有一个独特的信息级别,您现在可以按照所需的特定级别进行分组和总结。

一般来说,您可能会发现首先以长/整齐的格式获取数据更简单。这使得分组和聚合更加容易,这是矢量化/映射操作真正发挥作用的地方

使用您提供的数据,有一种方法可以做到这一点:

library(matlib)
library(tidyverse)

n_specimen <- ncol(vector1)

data.frame(t(vector1)) %>%
  rename_all(~str_replace(., "X", "v1_")) %>%
  bind_cols(
    data.frame(t(vector2)) %>%
      rename_all(~str_replace(., "X", "v2_"))
    ) %>%
  mutate(specimen = paste0("Specimen", 1:n_specimen)) %>%
  pivot_longer(-specimen, names_to = "vector", values_to = "value") %>%
  separate(vector, into = c("vector", "ix"), sep = "_", remove = TRUE) %>%
  group_by(specimen) %>%
  summarise(angle = angle(value[vector == "v1"], value[vector == "v2"])) 

  specimen  angle
  <chr>     <dbl>
1 Specimen1  146.
2 Specimen2  152.
3 Specimen3  135.

每一列都有一个独特的信息级别,您现在可以根据所需的具体程度进行分组和总结。

您能否更新您的示例,以说明您希望如何处理“每个样本的多个角度”?解决每个样本只进行一次比较(这是您现在期望的输出)比解决任意数量的比较要简单。@andrew_reece示例已更新。总的来说,我想尝试为每个角度写一列,并为每个角度写一个单独的方程。每个预期角度列代表了在研究领域感兴趣的每个样本上可测量的特定特征。感谢更新。请查看答案,并在各自的评论源中回复,让我们知道我们是否遗漏了任何内容。您能否更新您的示例,以说明您希望如何处理“每个样本的多个角度”?解决每个样本只进行一次比较(这是您现在期望的输出)比解决任意数量的比较要简单。@andrew_reece示例已更新。总的来说,我想尝试为每个角度写一列,并为每个角度写一个单独的方程。每个预期角度列代表了在研究领域感兴趣的每个样本上可测量的特定特征。感谢更新。请查看答案,并在各自的评论源中回复,让我们知道我们是否遗漏了任何内容。我更新了问题,以了解矩阵为何采用2x3格式。基本上,它是一个x,y向量,由两个点减去另一个点得到,每列代表一个样本。@user2352714(从R结构的角度来看)将这些向量存储在
列表中会更有意义。不仅向量
s与向量相关;使用
*apply
系列中的函数,还可以轻松地迭代
列表
元素。在你编辑之后,我现在不清楚这是否解决了你的问题。我将向您展示如何为每个样本创建角度矩阵。这解决了你的问题吗?老实说,我甚至不确定创建向量的最佳方法是什么。我对R不是很在行。我试图找到所有样本的点1-2和3-4形成的线之间的角度。角度函数表示它们需要矢量格式的信息,但没有说明如何从笛卡尔数据中获取,我能找到的最好结果是两个地标之间的x和y差异。不清楚函数是否需要线性向量或类
vector
的对象或什么。@user2352714 R中的向量是包含相同类型元素的基本数据结构
c(1.0,10,20)
是一个
数值的
向量
c(“A”、“O”、“L”)
是一个
字符
向量;等等函数
角度
需要一个
数值
向量,请参见文档
?角度
中给出的示例。我更新了问题,以了解矩阵为何采用2x3格式。基本上,它是一个x,y向量,由两个点减去另一个点得到,每列代表一个单独的sp