Функция NLS по группам - PullRequest
       66

Функция NLS по группам

0 голосов
/ 09 октября 2018

У меня есть набор данных, в котором я хочу применить нелинейные наименьшие квадраты по группам.Это продолжение моего предыдущего вопроса: Функция NLS - Максимальное число итераций превышает

Набор данных выглядит следующим образом:

df
x        y    GRP
0        0      1
426   9.28      1
853   18.5      1
1279  27.8      1
1705  37.0      1
2131  46.2      1
0        0      2
450   7.28      2
800   16.5      2
1300  30.0      2
2000  40.0      2
2200  48.0      2  

Если бы я это сделалс одной группой это было бы так:

df1<-filter(df, GRP==1)

a.start <- max(df1$y)
b.start <- 1e-06
control1 <- nls.control(maxiter= 10000,tol=1e-02, warnOnly=TRUE)
nl.reg <- nls(y ~ a * (1-exp(-b * x)),data=df1,start= 
list(a=a.start,b=b.start),
           control= control1)
coef(nl.reg)[1]
coef(nl.reg)[2]

> coef(nl.reg)[1]
       a 
5599.075 
> coef(nl.reg)[2]
       b 
3.891744e-06 

Я бы сделал то же самое для GRP2.Я хочу, чтобы мой конечный результат выглядел так:

x        y    GRP                       a                       b
0        0      1                5599.075            3.891744e-06
426   9.28      1                5599.075            3.891744e-06
853   18.5      1                5599.075            3.891744e-06
1279  27.8      1                5599.075            3.891744e-06
1705  37.0      1                5599.075            3.891744e-06
2131  46.2      1                5599.075            3.891744e-06
0        0      2    New Value for a GRP2    New Value for b GRP2     
450   7.28      2    New Value for a GRP2    New Value for b GRP2
800   16.5      2    New Value for a GRP2    New Value for b GRP2
1300  30.0      2    New Value for a GRP2    New Value for b GRP2
2000  40.0      2    New Value for a GRP2    New Value for b GRP2
2200  48.0      2    New Value for a GRP2    New Value for b GRP2

В идеале я думаю, что dplyr был бы лучшим способом, но я не могу понять, как это сделать.Вот как я думаю, это будет выглядеть примерно так:

control1 <- nls.control(maxiter= 10000,tol=1e-02, warnOnly=TRUE)
b.start <- 1e-06

df %>%
  group_by(GRP) %>%
  do(nlsfit = nls( form = y ~ a * (1-exp(-b * x)), data=., 
start= list( a=max(.$y), b=b.start),
      control= control1) ) %>%
  list(a = coef(nlsfit)[1], b = coef(nlsfit)[2])

Ошибка:

 in nlsModel(formula, mf, start, wts) : 
  singular gradient matrix at initial parameter estimates

Не совсем уверен, как это сделать, и любая помощь будет отличной.Спасибо!

1 Ответ

0 голосов
/ 09 октября 2018

Первоначально я получил то же сообщение об ошибке (повторно: не обнаружил объект 'y' в nls), что я сделал с ударом tidyverse, когда первоначально пытался использовать парадигму lapply-split-function, и начал искать: "[используя nls внутри функции ".Я изменил свое первоначальное использование attach на list2env:

sapply(  split( df , df$GRP), function(d){ dat <- list2env(d)
    nlsfit <- nls( form = y ~ a * (1-exp(-b * x)), data=dat, start= list( a=max(y), b=b.start),
          control= control1) 

list(a = coef(nlsfit)[1], b = coef(nlsfit)[2])} )
#---

  1            2            
a 14.51827     441.5489     
b 2.139378e-06 -6.775562e-06

Вы также получаете предупреждения, которые ожидали.Они могут быть подавлены с помощью suppressWarnings( ... )

Одним из предложений было использование attach.Что я и сделал с чрезвычайной неохотой, поскольку я часто предупреждал новичков не использовать attach.Но здесь это, казалось, заставило местную среду быть построенной.Мне удобнее использовать list2env как механизм удовлетворения nls.Вершина кода для nls привела меня к этому выбору:

if (!is.list(data) && !is.environment(data)) 
    stop("'data' must be a list or an environment")
...