代码之家  ›  专栏  ›  技术社区  ›  Vlad

R-ggplot2几何光滑单调光滑函数

  •  1
  • Vlad  · 技术社区  · 7 年前

    有可能使几何光滑产生单调递减函数吗?

    第一个例子看起来单调递减:

    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))
    

    geom smooth monotonic looks OK

    第二个例子看起来并不单调:

    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))
    

    enter image description here

    x = 25 to 65 ,然后再次下降。这不好-函数不需要随着x的增加而增加。

    我也试过用 nls() 具有单调递减函数,例如 y ~ 1/x ,或 y ~ exp(1/x) 但由于我有数千个数据集,未能找到一种自动查找起始值的有效方法。geom_smooth似乎在许多情况下都能很好地工作,除了第二个例子中的凹凸。

    1 回复  |  直到 7 年前
        1
  •  3
  •   LetEpsilonBeLessThanZero    7 年前

    如果你只是想要一个漂亮的曲线,那么你可以用这个:

    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)
    

    enter image description here

    我只是用一种很不和谐的方式强迫一条对数回归线,因为你有负值,但它得到了一条漂亮的曲线,至少看起来。。。

        2
  •  0
  •   CSJCampbell    7 年前

    骗局

    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)
    

    enter image description here

    推荐文章