You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何统计ggplot中两条geom_path曲线间的散点数量?

统计散点落在两条曲线间的高效方案(R语言)

针对数千个散点的场景,核心思路是通过插值建立曲线的x边界与y值的映射关系,再向量化判断每个散点是否落在区间内,全程避免循环,保证效率。

步骤说明

  1. 构建曲线的插值函数
    两条曲线对应x_plus(y)(上边界)和x_minus(y)(下边界),由于散点的y_points大概率和曲线上的y值不完全匹配,用approxfun()生成基于y的线性插值函数,能快速对任意y值计算对应的x上下限。如果曲线是非线性的,也可以用splinefun()做样条插值,精度更高。

  2. 向量化判断散点位置
    对每个散点的y_points,用插值函数得到对应的x_upper和x_lower,然后判断x_points是否满足x_lower ≤ x_points ≤ x_upper。

  3. 统计符合条件的点数
    直接对布尔结果求和,即可得到落在两条曲线间的点数。

代码示例

library(ggplot2)

# 1. 模拟数据集
# 构造两条曲线的数据源
df <- data.frame(
  y = seq(1, 100, by = 5),
  x_plus = seq(10, 200, by = 10) + rnorm(20, 0, 5),  # 上边界曲线
  x_minus = seq(5, 100, by = 5) + rnorm(20, 0, 3)    # 下边界曲线
)

# 构造散点数据(数千个点)
set.seed(123)
points_df <- data.frame(
  x_points = runif(5000, 0, 220),
  y_points = runif(5000, 1, 100)
)

# 2. 生成插值函数
x_plus_fun <- approxfun(df$y, df$x_plus, rule = 2)  # rule=2表示超出范围时取边界值
x_minus_fun <- approxfun(df$y, df$x_minus, rule = 2)

# 3. 计算每个散点对应的x上下限,并判断是否在区间内
points_df$in_range <- with(points_df, 
  x_minus_fun(y_points) <= x_points & x_points <= x_plus_fun(y_points)
)

# 4. 统计点数
in_range_count <- sum(points_df$in_range)
cat("落在两条曲线之间的点数:", in_range_count, "\n")

# 绘图验证(可选)
ggplot() +
  geom_path(data = df, aes(y = y, x = x_plus), color = "red", linewidth = 1) +
  geom_path(data = df, aes(y = y, x = x_minus), color = "blue", linewidth = 1) +
  geom_point(data = points_df, aes(x = x_points, y = y_points, color = in_range), size = 0.5) +
  scale_y_log10()  # 对数y轴

注意事项

  • 如果y轴对数刻度是通过scale_y_log10()绘图时实现的,原始数据无需转换,插值直接用原始y值即可;如果曲线的y已经是对数转换后的,需要把points_df$y_points也做对数转换后再传入插值函数。
  • 当曲线的y范围覆盖不了散点的y_points时,approxfun()的rule=2参数会自动取曲线的端点值作为边界,避免NA值影响统计;如果需要排除超出曲线y范围的点,可以先过滤y_points在range(df$y)之外的记录。
  • 针对超大数据量(比如10万+点),可以用data.table包的向量化操作进一步提升速度,逻辑和上述一致。

内容的提问来源于stack exchange,提问作者ZT_Geo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 22:30:52