有可能使geom_smooth产生单调递减函数吗?
第一个示例看起来单调递减:
library(tidyverse)
df <- structure(list(x = c(-55, 11, 19, 123, 133, 123, 123, 2, 86,
84, 179, 179, 179, 179, 25, 85, 84, 179, 179, 179, 179, 25, 86,
84, 179, 179, 179, 179, 25, 86, 84, 179, 179, 179, 179, 25, 86,
70, 123, 123, 123, 123, 0, -45, -45, -17, -17, -17, -17, -63,
48, 40, 67, 67, 67, 67, -25, 11, 10, 67, 67, 67, 67, -25, 11,
10, 67, 67, 67, 67, -25, 11), y = c(126, -29, -37, -63, -76,
-70, -58, 23, -17, -26, -74, -72, -70, -73, 6, -24, -10, -54,
-67, -59, -59, 27, -37, -12, -51, -69, -61, -58, 52, -52, -25,
-46, -64, -54, -55, 41, -11, -22, -48, -63, -57, -56, 34, 17,
56, -26, -13, -16, -25, 99, -39, -16, -54, -74, -52, -60, 9,
-32, -17, -62, -66, -50, -65, 60, -34, -24, -62, -76, -62, -58,
27, -36)), row.names = c(NA, -72L), class = "data.frame")
ggplot(df) + geom_point(aes(x, y)) + geom_smooth(aes(x, y))
第二个例子看起来并不单调:
df <- structure(list(x = c(33, -14, -14, -15, -10, -33, 2, 28, -33,
-33, -33, -33, -48, -22, 0, 33, 33, 33, 33, 3, 37, 75, 17, 17,
17, 17, 8, 95, 151, 67, 67, 67, 67, 31, 95, 151, 67, 67, 67,
67, 31, 95, 151, 67, 67, 67, 67, 31, 95, 151, 67, 67, 67, 67,
31, 95, 151, 67, 67, 67, 67, 31, 95, 139, 50, 50, 50, 50, 16,
56, 101, 33), y = c(-50, 75, 77, 137, 36, 97, -42, -67, 147,
163, 176, 132, 384, 100, 65, -17, -53, -11, -49, -48, -77, -87,
-25, -23, -11, 4, -45, -54, -81, -36, -19, 3, -26, -6, -68, -74,
-11, -21, 32, -28, -19, -41, -74, -36, -33, 47, -4, -35, -52,
-69, -8, 47, 0, -45, 26, -48, -71, 19, 14, 18, -40, -71, -44,
-61, 19, 5, -16, 15, 29, -48, -72, 0)), row.names = c(NA, -72L
), class = c("tbl_df", "tbl", "data.frame"))
ggplot(df) + geom_point(aes(x, y)) + geom_smooth(aes(x, y))
您可以看到函数下降,然后在x = 25 to 65
之间上升,然后再次下降。那就不好了-该函数永远不需要随着x的增加而上升。
我还尝试将nls()
与单调递减函数一起使用,例如y ~ 1/x
或y ~ exp(1/x)
,但是由于我有成千上万的数据集,因此未能找到有效的自动查找起始值的方法。 geom_smooth似乎在许多情况下都可以很好地工作,除了第二个示例中带有凸起的情况。
答案 0 :(得分:3)
如果您只想要漂亮的曲线,则可以使用以下方法:
library(tidyverse)
df <- structure(list(x = c(33, -14, -14, -15, -10, -33, 2, 28, -33,
-33, -33, -33, -48, -22, 0, 33, 33, 33, 33, 3, 37, 75, 17, 17,
17, 17, 8, 95, 151, 67, 67, 67, 67, 31, 95, 151, 67, 67, 67,
67, 31, 95, 151, 67, 67, 67, 67, 31, 95, 151, 67, 67, 67, 67,
31, 95, 151, 67, 67, 67, 67, 31, 95, 139, 50, 50, 50, 50, 16,
56, 101, 33), y = c(-50, 75, 77, 137, 36, 97, -42, -67, 147,
163, 176, 132, 384, 100, 65, -17, -53, -11, -49, -48, -77, -87,
-25, -23, -11, 4, -45, -54, -81, -36, -19, 3, -26, -6, -68, -74,
-11, -21, 32, -28, -19, -41, -74, -36, -33, 47, -4, -35, -52,
-69, -8, 47, 0, -45, 26, -48, -71, 19, 14, 18, -40, -71, -44,
-61, 19, 5, -16, 15, 29, -48, -72, 0)), row.names = c(NA, -72L
), class = c("tbl_df", "tbl", "data.frame"))
plot = ggplot(df) +
geom_point(aes(x, y)) +
geom_smooth(aes(x, y),
method = "lm",
formula = y ~ log(x-min(df$x)-1),
se = FALSE)
print(plot)
由于您的值为负值,我只是以对角的方式强迫对数回归线,但至少会出现一条漂亮的曲线……
答案 1 :(得分:0)
对于后代,请查看软件包骗局以获取形状受限制的附加模型。
library(ggplot2)
library(scam)
df <- structure(list(x = c(33, -14, -14, -15, -10, -33, 2, 28, -33,
-33, -33, -33, -48, -22, 0, 33, 33, 33, 33, 3, 37, 75, 17, 17,
17, 17, 8, 95, 151, 67, 67, 67, 67, 31, 95, 151, 67, 67, 67,
67, 31, 95, 151, 67, 67, 67, 67, 31, 95, 151, 67, 67, 67, 67,
31, 95, 151, 67, 67, 67, 67, 31, 95, 139, 50, 50, 50, 50, 16,
56, 101, 33), y = c(-50, 75, 77, 137, 36, 97, -42, -67, 147,
163, 176, 132, 384, 100, 65, -17, -53, -11, -49, -48, -77, -87,
-25, -23, -11, 4, -45, -54, -81, -36, -19, 3, -26, -6, -68, -74,
-11, -21, 32, -28, -19, -41, -74, -36, -33, 47, -4, -35, -52,
-69, -8, 47, 0, -45, 26, -48, -71, 19, 14, 18, -40, -71, -44,
-61, 19, 5, -16, 15, 29, -48, -72, 0)), row.names = c(NA, -72L
), class = c("tbl_df", "tbl", "data.frame"))
如果您非常关注样条线的形状,则该公式将需要进行一些修补,
但是当您定义时,此方法将始终创建单调递减拟合
样条为单调递减("mpd"
)。
# for some reason an object called `weight` needs
# to be present at ggplot2_3.1.1
weight <- rep(1, times = nrow(df))
ggplot(df, mapping = aes(x, y)) +
geom_point() +
geom_smooth(method = "scam",
# b-spline monotonic deceasing
# see ?shape.constrained.smooth.terms
formula = y ~ s(x, k = 5, bs = "mpd"),
se = FALSE)