如何筛选位于两条LOESS曲线之间的散点图数据?
I get it—you’ve got your plot set up with the green center line, upper/lower black loess curves, and blue scatter points, but you’re stuck on keeping only the points that sit between those two black curves. The issue with using which(), filter(), or subset() directly is that ggplot’s geom_smooth() calculates those curve predictions on the fly for plotting, not for your raw data. Here’s how to fix that by explicitly computing the curve bounds first:
Step 1: Fit the Loess Models for Upper/Lower Curves
First, we need to replicate the loess fits that geom_smooth() uses for your upper (y+1~x) and lower (y-1~x) curves. Let’s use mtcars as your data source, and I’ll assume you’re using specific columns for x and y (swap these out for your actual variables if needed):
library(tidyverse) # Define your base data with explicit x and y columns (adjust to your actual variables!) df <- mtcars %>% mutate(x = wt, y = mpg) # Fit the two loess models matching your geom_smooth formulas upper_model <- loess(y + 1 ~ x, data = df) lower_model <- loess(y - 1 ~ x, data = df)
Step 2: Add Predictions to Your Data Frame
Next, calculate the predicted upper and lower bounds for every row in your data, then append these values to your original data frame:
df_with_bounds <- df %>% mutate( upper_bound = predict(upper_model, newdata = .), lower_bound = predict(lower_model, newdata = .) )
Step 3: Filter Points Between the Bounds
Now you can use filter() to keep only the points where the y value falls between the lower_bound and upper_bound:
filtered_points <- df_with_bounds %>% filter(y >= lower_bound & y <= upper_bound)
Step 4: Verify with a Plot
You can plot the filtered points to confirm they’re exactly the ones between your two black curves:
ggplot(filtered_points, aes(x, y)) + geom_point(color = "blue") + geom_smooth(formula = y~x, method = "loess", color = "green3", se = FALSE, size = 0.5) + geom_smooth(formula = y+1~x, method = "loess", color = "gray20", se = FALSE, size = 0.5) + geom_smooth(formula = y-1~x, method = "loess", color = "gray20", se = FALSE, size = 0.5)
Why Your Previous Attempts Didn’t Work
When you tried filter() or subset() directly, you were probably trying to use the formula y+1~x directly in the filter logic—but that formula doesn’t translate to row-wise comparisons. You need to first compute the actual predicted values from the loess model for each x, then compare each point's y to those precomputed bounds.
内容的提问来源于stack exchange,提问作者Kshitij15571

