geom_smooth在部分facet_wrap中无法连接含NA的geom_point问题
问题:geom_smooth()无法在所有分面中连接数据点
你有一个包含study、celltype、value、time.numeric的data.frame,尝试用geom_smooth()连接所有geom_point(),但发现该函数仅在部分分面生效,同时收到以下警告:
Warning messages: 1: Removed 46 rows containing non-finite values (stat_smooth). 2: In simpleLoess(y, x, w, span, degree = degree, parametric = parametric, ... : span too small. fewer data values than degrees of freedom. 3: In simpleLoess(y, x, w, span, degree = degree, parametric = parametric, ... : pseudoinverse used at -1.0079
数据集结构
a <- structure(list(study = c("Milnari", "Rajesh", "Steele", "de Graaf", "Chow_RT", "Steele", "Milnari", "Dux", "de Graaf", "Basile_Bcell", "Steele", "de Graaf", "Renshaw", "Renshaw", "Milnari", "Rajesh", "Steele", "Rajesh", "Rajesh", "Dux", "Ness", "Basile_Tcell", "Rajesh", "de Graaf", "Milnari", "Dux", "Ness", "de Graaf", "de Graaf", "Rajesh", "Rajesh", "Chow_RT", "Steele", "de Graaf", "Milnari", "Ness", "Dux", "Dux", "Ness", "Basile_Bcell", "Dux", "Milnari", "Renshaw", "Basile_Bcell", "Steele", "Renshaw", "Rajesh", "Rajesh", "Milnari", "de Graaf"), celltype = c("Lymph", "Granulo", "Granulo", "Mono", "WBC", "Mono", "Lymph", "Lymph", "Lymph", "Lymph", "Granulo", "Granulo", "WBC", "WBC", "Lymph", "WBC", "Lymph", "Granulo", "Granulo", "Granulo", "Lymph", "Lymph", "Granulo", "Mono", "Lymph", "Granulo", "Lymph", "Mono", "Granulo", "WBC", "WBC", "WBC", "Granulo", "Lymph", "Granulo", "Lymph", "Lymph", "Lymph", "Lymph", "Lymph", "Lymph", "Lymph", "WBC", "Lymph", "Granulo", "WBC", "WBC", "Granulo", "Granulo", "Granulo"), value = c(93L, 81L, 50L, NA, NA, NA, NA, 88L, NA, NA, 42L, NA, 6L, NA, 93L, NA, 69L, 100L, NA, 25L, NA, 85L, 70L, NA, NA, 10L, 80L, NA, NA, NA, 80L, 85L, NA, NA, NA, NA, NA, NA, NA, 75L, NA, NA, NA, NA, 48L, 30L, NA, NA, NA, 58L ), time.numeric = c(1.5, 2, 2, 4, 48, 5, 2, 0.5, 4, 2, 4, 4, 48, 4, 1, 6, 3, 0.5, 1, 1, 24, 24, 4, 6, 48, 1.5, 1, 48, 6, 3, 2, 1, 1.5, 2, 5, 2, 2, 5, 6, 24, 48, 2, 2, 4, 3, 24, 24, 3, 6, 5)), class = "data.frame", row.names = c(NA, -50L))
尝试的代码
ggplot(a, aes(x = time.numeric, y = value, color = study, fill = study)) + geom_point() + scale_x_continuous(trans = "log2") + facet_wrap(~ celltype) + geom_smooth(se = FALSE)
问题原因
- 有效数据量严重不足:
value列存在大量NA,50行数据中仅4行有效数据被保留用于拟合,多数分面下的有效数据点不足2个,无法满足默认loess模型的拟合要求(loess至少需要4个数据点)。 - 默认模型不兼容小样本:
geom_smooth()默认使用loess局部回归,该方法对数据量有要求,当数据点少于模型自由度时,会触发"span too small"警告,无法生成平滑曲线。 - 全局分组导致拟合拆分过细:全局aes中设置了
color=study和fill=study,这会让geom_smooth()按study分组拟合曲线,但很多study在对应分面下只有1个有效点,根本无法完成拟合。
解决办法
1. 取消不必要的分组,拟合全局曲线
如果目标是连接分面内所有数据点(不区分study),可以在geom_smooth()中覆盖全局分组,同时更换适合小样本的线性模型:
ggplot(a, aes(x = time.numeric, y = value)) + geom_point(aes(color = study)) + # 点保留study的颜色区分 scale_x_continuous(trans = "log2") + facet_wrap(~ celltype) + geom_smooth(se = FALSE, method = "lm") # 使用线性回归拟合
2. 预处理数据,过滤无效NA
先筛选出value非NA的行,减少无效数据干扰,再进行拟合:
a_clean <- a[!is.na(a$value), ] ggplot(a_clean, aes(x = time.numeric, y = value, color = study)) + geom_point() + scale_x_continuous(trans = "log2") + facet_wrap(~ celltype) + geom_smooth(se = FALSE, method = "lm")
3. 按study分组拟合(需确保每组数据足够)
如果必须按study分组拟合,先检查每个celltype + study组合的有效数据量,对数据点不足的分组可以跳过拟合,或合并相似分组:
# 先查看各分组的有效数据量 table(a_clean$celltype, a_clean$study) # 仅对数据量≥2的分组拟合 ggplot(a_clean, aes(x = time.numeric, y = value, color = study)) + geom_point() + scale_x_continuous(trans = "log2") + facet_wrap(~ celltype) + geom_smooth(se = FALSE, method = "lm", data = subset(a_clean, ave(!is.na(value), celltype, study, FUN = length) >= 2))
内容的提问来源于stack exchange,提问作者cmirian
相关产品推荐
相关产品推荐

