R: хранение регрессионных моделей

Я использую несколько моделей регрессии для моделирования проблемы, например. по одному на каждый день недели. Я хочу сохранить их в структуре данных в R, чтобы я мог вызывать их при необходимости. В качестве минимального примера проблемы, скажем, я хочу построить по одному для каждого значения z:

df = data.frame(z = rep(c('a', 'b'), each = 10),
            x = rep.int(1:10, times = 2), 
            y = rep.int(10:1, times = 2))

Наивно, я попробовал следующую попытку:

dt = data.table(df)

v.type = unique(dt$z)
v.loess = numeric(0)

for(i in v.type)
  v.loess = c(v.loess, loess(y ~ x, data = dt[z==i]))

dt.loess = data.table(type = v.type, model = v.loess)

Учитывая, например. type = a и x = 2.5, идея состояла в том, чтобы запустить что-то вроде этого:

predict(dt.loess[z == 'a', 'model', with = FALSE], newdata = 2.5)

Этот метод полностью терпит неудачу. Любая помощь приветствуется.


person user32259    schedule 09.04.2013    source источник
comment
Я не перед своим ПК. Можете ли вы проверить, что class вектора модели передается в функцию predict?   -  person Nishanth    schedule 09.04.2013
comment
разве это не должно быть for(i in v.type) ?   -  person Beasterfield    schedule 09.04.2013


Ответы (2)


loess() возвращает объект S3 класса loess. Внутренне эти объекты представлены в виде списков, что можно увидеть, если вызвать для них str().

Теперь есть в основном две причины, по которым ваши решения терпят неудачу:

  1. В цикле for вы объединяете эти объекты (см. здесь списки) с помощью c(), который просто объединяет элементы списка (или поля объекта) в один больший список, в результате чего получается недопустимый объект класса loess. Затем вы пытаетесь сохранить этот список как столбец в файле data.table.

  2. Я не понимаю, почему вы хотите хранить модели в конце в data.table, но я почти уверен, что это невозможно сделать, поскольку элементы столбца должны быть (насколько я помню) атомарными векторами или списки. Я бы предпочел хранить модели в именованном списке и оставлять их там.


Решение с использованием базы R

model <- list()
for( i in unique(dt$z) ){
  model[[i]] <- loess(y ~ x, data = dt[ z==i ] )
}

Решение с использованием plyr

library("plyr")
model <- dlply( df, "z", function(data){
  loess( y ~ x, data = data )
} )

Или еще короче:

library("plyr")
model <- dlply( df, "z", loess, formula = quote(y ~ x) )

Последние два решения могут быть применены к обоим: data.table и data.frame, но в этом случае вы не получите никаких преимуществ data.table. Таким образом, вы должны решить, что в конце концов быстрее и менее подвержено ошибкам.


Во всех трех случаях вы можете позвонить

predict( model[["a"]], newdata = 2.5)
[1] 8.5
person Beasterfield    schedule 09.04.2013
comment
Спасибо не только за ответ, но и за чрезвычайно поучительное и полезное объяснение того, почему мой был таким неправильным. - person user32259; 10.04.2013
comment
Это работает с набором данных примера, однако все описанные выше подходы приводят к следующей ошибке с моим фактическим набором данных: Error in simpleLoess(y, x, w, span, degree, parametric, drop.square, normalize, : invalid 'x'. Существуют ли «обычные виновники» такого сообщения об ошибке, на что можно ответить, только посмотрев на мой фактический набор данных? - person user32259; 10.04.2013
comment
Лично я не знаю обычных виновников, но было бы очень полезно, если бы вы хотя бы попытались связать проблему с подмножеством data.frame, для которого возникает ошибка. Возможно, просто напечатав unique(data$z) в функции plyr или i в цикле for. Подмножество выглядит странно? - person Beasterfield; 10.04.2013
comment
задача решена. некоторые мошенники NA прокрались внутрь. Спасибо за вашу помощь, Бистерфилд. - person user32259; 10.04.2013

Во-первых, использование c для объединения результатов дает забавные результаты; лучше заполнить список напрямую. Во-вторых, использовать data.table для получения результатов сложно; Я не эксперт по data.table, поэтому я бы просто использовал результаты прямо из списка.

v.type = unique(df$z)
v.loess = list()
for(i in v.type) {
  v.loess[[i]] <- loess(y ~ x, data = df[df$z==i,])
}
predict(v.loess$a, newdata=2.5)
predict(v.loess$b, newdata=2.5)
person Aaron left Stack Overflow    schedule 09.04.2013
comment
Извините, ваш ответ не был опубликован, когда я начал писать свой. Теперь похоже, что я только что скопировал твой :-/ - person Beasterfield; 09.04.2013
comment
Спасибо, что нашли время ответить Аарону, - person user32259; 10.04.2013