如何用R计算起始点与多个终点间的夹角及距离?
R语言计算起始点到终点的距离及相邻终点夹角问题解决
需求说明
给定包含起始点(如A、B)及其对应多个终点的数据集,需完成两个任务:
- 计算起始点到每个终点的欧氏距离,新增
distance列 - 计算起始点与相邻终点形成的夹角(如A₁-A-A₂、A₂-A-A₃这类以起始点为顶点的夹角),新增
angle列
数据集
df <- structure(list(start_point = c("A", "A", "A", "A", "B", "B", "B"), start_point_x = c(1, 1, 1, 1, 2, 2, 2), start_point_y = c(1, 1, 1, 1, 2, 2, 2), end_point = c("A_1", "A_2", "A_3", "A_4", "B_1", "B_2", "B_3"), end_point_x = c(1.5, 1.3, 1.69, 2.45, 3.24, 1.97, 2.15), end_point_y = c(1.7, 2, 0.63, 1.32, 2.15, 1.85, 3.89)), row.names = c(NA, -7L), class = "data.frame")
原代码报错原因
你尝试用LearnGeom::Angle结合apply和lag时出现Error in A[[1]] - B[[1]] : non-numeric argument to binary operator,核心问题是:
apply会将数据框的行转换为字符型向量,导致LearnGeom::Angle接收到非数值参数lag在apply的行级操作中无法正确获取组内上一行的终点坐标,进一步引发类型错误
解决方案
使用dplyr分组处理,直接操作数值列,避免类型转换问题,同时正确实现组内相邻坐标的关联:
完整代码
# 加载依赖包 library(dplyr) library(LearnGeom) # 处理数据:计算距离和夹角 result_df <- df %>% # 按起始点分组,保证每组内的终点是有序的 group_by(start_point) %>% # 1. 计算起始点到终点的欧氏距离 mutate(distance = sqrt((end_point_x - start_point_x)^2 + (end_point_y - start_point_y)^2), # 获取组内上一个终点的坐标 prev_end_x = lag(end_point_x), prev_end_y = lag(end_point_y), # 2. 计算夹角:顶点为起始点(B),两边为前一个终点(A)和当前终点(C) angle = case_when( is.na(prev_end_x) ~ NA_real_, # 第一个终点无前置点,夹角设为NA TRUE ~ LearnGeom::Angle( A = c(prev_end_x, prev_end_y), B = c(start_point_x, start_point_y), C = c(end_point_x, end_point_y) ) )) %>% # 移除临时辅助列 select(-prev_end_x, -prev_end_y) %>% # 取消分组 ungroup() # 输出结果 print(result_df)
代码说明
- 距离计算:直接用欧氏距离公式,无需额外函数,高效且直观
- 夹角计算:
- 按
start_point分组后,lag能准确获取组内上一行的终点坐标 - 第一个终点因无前置相邻点,夹角设为
NA,符合逻辑 - 用
case_when替代ifelse,代码可读性更强 - 直接传递数值列给
LearnGeom::Angle,避免了类型转换错误
- 按
结果示例
运行后得到的数据集会新增distance和angle列,示例输出:
# A tibble: 7 × 8 start_point start_point_x start_point_y end_point end_point_x end_point_y distance angle <chr> <dbl> <dbl> <chr> <dbl> <dbl> <dbl> <dbl> 1 A 1 1 A_1 1.5 1.7 0.860 NA 2 A 1 1 A_2 1.3 2 1.04 23.2 3 A 1 1 A_3 1.69 0.63 0.786 124. 4 A 1 1 A_4 2.45 1.32 1.48 97.4 5 B 2 2 B_1 3.24 2.15 1.25 NA 6 B 2 2 B_2 1.97 1.85 0.152 98.4 7 B 2 2 B_3 2.15 3.89 1.90 92.1
内容的提问来源于stack exchange,提问作者mto23
相关产品推荐
相关产品推荐

