如何判断ggplot2绘制的图表中各数据点所属的特定分区
解决方案
方法一:空间多边形匹配法(推荐,适配任意形状分区边界)
无需手动梳理复杂的不等式判断逻辑,通用性极强,后续调整分区边界也不需要重写判断规则。
实现步骤:
- 加载依赖包
install.packages("sf") library(sf) library(tidyverse)
- 定义边界函数,采样构造分区多边形
# 定义三条分区边界函数 f1 <- function(x) ((x - 1.05) * 5)^1.0526 f2 <- function(x) ((x - 1.1) * 1.5)^1.0989 f3 <- function(x) x # 采样x轴坐标点,数值越大分区匹配精度越高 x_seq <- seq(-2, 20, length.out = 1000) # 生成三条边界的完整坐标 line1 <- tibble(x = x_seq, y = f1(x)) %>% filter(x >= 1.31) line2 <- tibble(x = x_seq, y = f2(x)) %>% filter(x >= 2.82) line3 <- tibble(x = x_seq, y = f3(x)) # 构造四个分区的闭合多边形空间对象 zone_sf <- list( # CCS区:最下方 CCS = rbind( c(-2, 1), line3 %>% as.matrix(), c(20, 1), c(-2, 1) ), # SD区:左上方 SD = rbind( c(-2, 1000), line3 %>% filter(x <= 2.82) %>% as.matrix(), c(-2, 0), c(-2, 1000) ), # CC区:中间区域 CC = rbind( line1 %>% as.matrix(), rev(line2 %>% as.matrix()), line3 %>% filter(x >= 2.82) %>% arrange(desc(x)) %>% as.matrix(), line3 %>% filter(x == 2.82) %>% as.matrix(), line1[1,] %>% as.matrix() ), # TC区:右上方 TC = rbind( c(20, 1000), rev(line1 %>% as.matrix()), c(20, f1(20)), c(20, 1000) ) ) %>% lapply(st_polygon) %>% st_sfc(crs = NA) %>% st_sf(zone = c("CCS", "SD", "CC", "TC"), geometry = .)
- 匹配样本点所属分区
# 样本点转为空间点对象 sample_data_sf <- sample_data %>% st_as_sf(coords = c("x", "y"), remove = F) # 关联得到每个点的分区标签 sample_data_with_zone <- st_join(sample_data_sf, zone_sf)
- 按分区给点上色绘图
ggplot( data = sample_data_with_zone, aes(x, y, color = zone) ) + geom_point(size = 3) + scale_x_continuous( expand = c(0, 0), minor_breaks = NULL, breaks = seq(-2, 20, by = 2) ) + scale_y_continuous( trans = "log10", expand = c(0, 0), minor = c(seq(1, 10, by = 1), seq(10, 100, by = 10), seq(100, 1000, by = 100)) ) + coord_cartesian( xlim = c(-2, 20), ylim = c(1, 1000), expand = c(0, 0) ) + geom_function(fun = f1, xlim = c(1.31, 20)) + geom_function(fun = f2, xlim = c(2.82, 20)) + geom_function(fun = f3, xlim = c(-2, 20)) + geom_text( data = zoning_data, aes(x = x, y = y, label = label), inherit.aes = F ) + theme(aspect.ratio = 1)
方法二:函数判断法(适合边界规则简单的场景)
如果不想额外安装空间分析包,可以直接根据边界函数写条件判断打标签:
# 定义带定义域校验的边界函数 f1 <- function(x) ifelse(x >= 1.31, ((x - 1.05) * 5)^1.0526, Inf) f2 <- function(x) ifelse(x >= 2.82, ((x - 1.1) * 1.5)^1.0989, Inf) f3 <- function(x) x # 给样本点打分区标签 sample_data_with_zone <- sample_data %>% mutate( zone = case_when( y < f3(x) ~ "CCS", x < 1.31 ~ "SD", y < f2(x) ~ "CC", y < f1(x) ~ "CC", y >= f1(x) ~ "TC" ) )
得到带分区标签的数据后,参考方法一的绘图代码即可实现分色展示。
内容的提问来源于stack exchange,提问作者erdi
相关产品推荐
相关产品推荐

