Як згладити дані та змусити монотонність


14

У мене є деякі дані, які я хотів би вирівняти, щоб згладжені точки монотонно зменшувалися. Мої дані різко зменшуються, а потім починають плато. Ось приклад використання R

df <- data.frame(x=1:10, y=c(100,41,22,10,6,7,2,1,3,1))
ggplot(df, aes(x=x, y=y))+geom_line()

графік даних згладжувати

Яка хороша техніка розгладження я могла використовувати? Крім того, було б непогано, якщо я можу змусити 1-ту згладжену точку бути близькою до моєї спостережуваної точки.


1
Я помічаю, що ваші приклади значення цілі. Чи підраховуються ваші реальні цінності? Якби вони були, то (хоча це не є гарантією одноманітності, для таких даних, як правило, це все-таки надасть), щось подібне може бути корисним:plot(y~x,data=df); f=fitted( glm( y~ns(x,df=4), data=df,family=quasipoisson)); lines(df$x,f)
Glen_b -Встановити Моніку,

Подібне запитання з відповіддю: stats.stackexchange.com/questions/206073/…
kjetil b halvorsen

Відповіді:


18

Це можна зробити, використовуючи пеналізовані сплайни з обмеженнями монотонності через mono.con()і pcls()функції в пакеті mgcv . Нещодавно варто зробити, тому що ці функції не такі зручні як користувачі gam(), але кроки наведені нижче, в основному на основі прикладу ?pcls, модифікованого відповідно до наведених вами зразків даних:

df <- data.frame(x=1:10, y=c(100,41,22,10,6,7,2,1,3,1))

## Set up the size of the basis functions/number of knots
k <- 5
## This fits the unconstrained model but gets us smoothness parameters that
## that we will need later
unc <- gam(y ~ s(x, k = k, bs = "cr"), data = df)

## This creates the cubic spline basis functions of `x`
## It returns an object containing the penalty matrix for the spline
## among other things; see ?smooth.construct for description of each
## element in the returned object
sm <- smoothCon(s(x, k = k, bs = "cr"), df, knots = NULL)[[1]]

## This gets the constraint matrix and constraint vector that imposes
## linear constraints to enforce montonicity on a cubic regression spline
## the key thing you need to change is `up`.
## `up = TRUE` == increasing function
## `up = FALSE` == decreasing function (as per your example)
## `xp` is a vector of knot locations that we get back from smoothCon
F <- mono.con(sm$xp, up = FALSE)   # get constraints: up = FALSE == Decreasing constraint!

Тепер нам потрібно заповнити об'єкт, який передається тому, pcls()що містить деталі пеніалізованої обмеженої моделі, до якої ми хочемо вмістити

## Fill in G, the object pcsl needs to fit; this is just what `pcls` says it needs:
## X is the model matrix (of the basis functions)
## C is the identifiability constraints - no constraints needed here
##   for the single smooth
## sp are the smoothness parameters from the unconstrained GAM
## p/xp are the knot locations again, but negated for a decreasing function
## y is the response data
## w are weights and this is fancy code for a vector of 1s of length(y)
G <- list(X = sm$X, C = matrix(0,0,0), sp = unc$sp,
          p = -sm$xp, # note the - here! This is for decreasing fits!
      y = df$y,
          w = df$y*0+1)
G$Ain <- F$A    # the monotonicity constraint matrix
G$bin <- F$b    # the monotonicity constraint vector, both from mono.con
G$S <- sm$S     # the penalty matrix for the cubic spline
G$off <- 0      # location of offsets in the penalty matrix

Тепер ми можемо нарешті зробити примірку

## Do the constrained fit 
p <- pcls(G)  # fit spline (using s.p. from unconstrained fit)

pмістить вектор коефіцієнтів для базових функцій, відповідних сплайну. Для візуалізації встановленого сплайна ми можемо передбачити з моделі в 100 місцях в межах діапазону x. Ми робимо 100 значень, щоб отримати гарну рівну лінію на ділянці.

## predict at 100 locations over range of x - get a smooth line on the plot
newx <- with(df, data.frame(x = seq(min(x), max(x), length = 100)))

Для створення прогнозованих значень ми використовуємо Predict.matrix(), яка генерує матрицю такою, що при множенні на коефіцієнти pвиходить прогнозовані значення з пристосованої моделі:

fv <- Predict.matrix(sm, newx) %*% p
newx <- transform(newx, yhat = fv[,1])

plot(y ~ x, data = df, pch = 16)
lines(yhat ~ x, data = newx, col = "red")

Це дає:

введіть тут опис зображення

Я залишаю це за вами, щоб отримати дані в охайній формі для створення графіків з ggplot ...

Ви можете примусити ближче відповідати (частково відповісти на ваше запитання про те, як плавніше підходити перша точка даних), збільшивши розмірність базисної функції x. Наприклад, встановивши kрівний 8( k <- 8) і повторивши код, який ми отримуємо вище

введіть тут опис зображення

Ви не можете натиснути kнабагато вище на ці дані, і вам слід бути обережними щодо надмірного розміщення; все, що pcls()робиться - це вирішити проблему з найменшими штрафами з урахуванням обмежень та функцій, що надаються, це не робить вибір гладкості для вас - не те, що я знаю з ...)

Якщо ви хочете інтерполяції, то перегляньте базову функцію R, ?splinefunяка має сплайни Ерміта та кубічні сплайни з обмеженнями монотонності. Однак у цьому випадку ви не можете використовувати це, оскільки дані не є суто монотонними.


Спасибі. Я впевнений, що ваше рішення є відповідним, але воно настільки складне і заплутане, що я просто не можу його використати. splinefunбула і моя початкова думка (я інтерполюю), але spline(x=df$x, y=df$y, n=nrow(df), method="monoH.FC")і spline(x=df$x, y=df$y, n=nrow(df), method="hyman")обидві викликають помилки
Бен

1
Якщо ви просто спробуєте, я впевнений, що ви можете його використовувати; Я мало уявляю, що тут відбувається під капотом, але я це розробив, і я вказав місця, які вам знадобляться змінити. Припускаючи , що ви знаєте , деякі R звичайно . Більшість деталей - це імплементація, яку ви можете ігнорувати, якщо все, що ви хочете зробити, відповідає монотонно обмеженому сплайну. Чи хотіли б ви мені ще раз анотувати код, щоб виділити більше про те, що робиться кожен крок? Посилання в ?mono.conдодатково надає детальну інформацію про метод.
Відновіть Моніку - Г. Сімпсон,

Щодо того, чому splinefunвиникає помилка; Я щойно зрозумів, ви можете помістити монотонний сплайн, який інтерполює дані, які самі по собі не є монотонними. Спостереження на x = 6рівні більше y, ніж спостереження на x = 5. Вам просто доведеться ігнорувати цю частину відповіді :-)
Відновіть Моніку - Г. Сімпсон,

Зрозумів. І немає потреби - я досить досвідчений користувач R. Мені просто подобається розуміти математику, яку я використовую, і, здається, це рішення досить багато відбувається під кришкою. Ще раз дякую за вашу допомогу.
Бен

Я додав кілька записок, щоб пояснити, що кожна річ є чи робить; головний момент, який слід зазначити, полягає в тому, що обмеження монотонності накладаються конкретним набором обмежень нерівності, який mono.conповертається за кубічний сплайн. ?pclsє приклади для тонких пластинних сплайнів і моделей добавок, які менш зручні для користувачів, ніж вище, але які можуть викрити трохи більше математики, якщо ви знайомі з математикою для тих типів сплайну (я не такий знайомий сам).
Відновіть Моніку - Г. Сімпсон,

13

Нещодавній пакет шахрайства Наталії Пії та заснований на папері Pya & Wood (2015) "Форма, обмежена моделями добавок" може значно полегшити частину процесу, згаданого у відмінній відповіді Гевіна.

library(scam)
con <- scam(y ~ s(x, k = k, bs = "mpd"), data = df)
plot(con)

Ви можете використовувати декілька функцій bs - у вищесказаному я використовував mpd для "монотонного зменшення P-сплайна", але він також має функції, які забезпечують опуклості або увігнутість окремо або поряд з монотонними обмеженнями.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.