Is there a way to fit loess to data with the constraint that it can only have one inflection point? If not how can I approximate it? I understand that I could use a larger span with loess, but that is not what I am looking for.
df <- structure(list(testage = c(0, 11, 15, 16, 17, 18, 19, 20, 21,
23, 24, 25, 27, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 71), val = c(-6,
-0.72, 0.415, 0.479, 0.36, 0.556, 0.682, 0.695, 0.631, 0.685,
0.662, 0.538, 0.33, 0.64, 0.755, 0.48, 0.554, 0.675, 0.56, 0.545,
0.631, 0.611, 0.45, 0.395, 0.532, 0.536, 0.37, 0.552, 0.429,
0.45, 0.331, 0.316, 0.47, 0.144, -0.044, 0.065, 0.17, 0.29, 0.111,
-0.007, -0.018, -0.048, -0.187, -0.292, -0.273, -0.175, -0.476,
-0.145, -0.603, -0.279, -0.528, -0.626, -0.641), n = c(10000,
1670, 52, 43, 52, 66, 26, 9, 10, 10, 13, 11, 7, 57, 27, 40, 37,
31, 68, 59, 55, 63, 66, 91, 64, 74, 50, 49, 84, 55, 55, 68, 60,
76, 45, 64, 44, 29, 33, 25, 17, 25, 21, 20, 18, 32, 13, 20, 13,
8, 7, 7, 8)), class = "data.frame", row.names = c(NA, -53L))
df %>%
ggplot(aes(x=testage, y=val, weight=n)) +
geom_point() +
scale_x_continuous(name = 'Age', limits = c(0,70)) +
scale_y_continuous(limits = c(-6,0.8), name = expression(paste("Avg. ",theta))) +
geom_smooth(size = 1, se=T, fullrange =T, span = 0.3) +
geom_hline(yintercept=0) +
geom_vline(xintercept=0)

If you use the
geom_smooth()geometry inggplot2, you can specify the number of smoothing points asn = 3. (You need this to be 3 because the first two are the first and last data point; the third will be the inflection point in the middle.)You can try smoothing it out further by increasing the
spanargument. It's still not terribly smooth around the inflection point, but possibly the best you're going to get.