Как построить подгонку поверхности по 3D-данным в R?

#r #ggplot2 #shiny #3d #plotly

#r #ggplot2 #блестящий #3D #plotly

Вопрос:

У меня есть точечный график 3D, который отображается следующим образом:

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

3D-набор данных очень большой, поэтому я не могу включить его сюда. Можно попытаться ответить на этот вопрос, используя стандартные наборы данных, такие как mtcars или iris .

Моя попытка построить эту диаграмму рассеяния 3D:

 x <- rbind(A_0,A_1,A_2,A_3) 
fig1 <- x %>% plot_ly(x= ~x,y=~y,z = ~z, color= ~key,type="scatter3d", size = 0.5)
fig1 
 

A_0, A_1, A_2, A_3 существуют ли разные 3 * n dataframes , которые объединяются вместе с использованием rbind и дифференцируются с помощью ключа, включенного в каждый dataframe

Я пытался подгонять поверхность различными методами, такими как add_surface() , add_trace() , изменение типа на 'mesh3D'

Но результирующая подгонка поверхности — это не то, что я хочу, мне нужна гладкая подгонка поверхности по этим данным разброса. Ошибка, которую я получаю, заключается в следующем: z is not a numeric matrix.

Есть ли лучший способ подгонки поверхности, чего мне здесь не хватает?

PS Я бы предпочел визуализировать график с ggplot() помощью , plot_ly() , ggplotly() .

Ответ №1:

Вы могли бы сначала подогнать модель, используя что-то вроде gam() , а затем построить прогнозы. Во-первых, мы можем подогнать GAM к данным. В этом случае hp и wt являются двумя независимыми переменными (т. Е. осями x и y на диаграмме выше). qsec переменная отображается на оси z и является зависимой переменной в модели.

 data(mtcars)
library(mgcv)
mod <- gam(qsec ~ te(hp)   te(wt)   ti(hp, wt), data=mtcars)
 

Далее нам нужно сделать некоторые прогнозы для модели при различных комбинациях hp и wt . Самый простой способ сделать это — создать последовательность значений для каждой переменной, которая идет от их минимумов к максимумам. Это то, что делают приведенные ниже команды. Он создает последовательность из 25 равномерно распределенных значений, идущих от минимума к максимуму каждой независимой переменной.

 hp.seq <- seq(min(mtcars$hp, na.rm=TRUE), max(mtcars$hp, na.rm=TRUE), length=25)
wt.seq <- seq(min(mtcars$wt, na.rm=TRUE), max(mtcars$wt, na.rm=TRUE), length=25)
 

Далее мы можем создать функцию, которая будет генерировать прогнозы. Поскольку мы собираемся использовать outer() ниже, мы должны заставить функцию принимать два ввода и x и a y . Пары x-y, которые мы собираемся передать, являются значениями hp и wt используются для прогнозов. Функция создает фрейм данных, который имеет одно наблюдение и две переменные — hp и wt . Он использует этот новый фрейм данных для генерации единого прогноза из модели с использованием predict() функции.

 predfun <- function(x,y){
  newdat <- data.frame(hp = x, wt=y)
  predict(mod, newdata=newdat)
}
 

Затем мы применяем эту функцию прогнозирования к последовательностям данных, которые мы сделали выше. Мы используем outer() функцию outer-product для создания матрицы 25×25 прогнозируемых значений для каждой комбинации hp.seq и wt.seq . Перенос predfun Vectorize() предотвращает ошибки, связанные с проблемами длины замены.

 fit <- outer(hp.seq, wt.seq, Vectorize(predfun))
 

Наконец, мы можем собрать все вместе plot_ly . Мы используем add_marker() для добавления точек и add_surface добавления прогнозов.

 plot_ly() %>% 
  add_markers(x = ~mtcars$hp, y=mtcars$wt, z=mtcars$qsec) %>% 
  add_surface(x = ~hp.seq, y = ~wt.seq, z = t(fit))

 

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

Комментарии:

1. Он работает нормально, но можете ли вы объяснить, как это работает, чтобы я мог изменять разные параметры для улучшения подгонки немного лучше, я особенно не мог понять эту строку: mod <- gam (qsec ~ te (hp) te (wt) ti (hp, wt), data = mtcars), а также функция прогнозирования.

2. @kolas0202 Я добавил некоторые пояснения выше. gam() Функция соответствует обобщенной аддитивной модели. Спецификация RHS (~ te(hp) te(wt) ti(hp,wt) ) соответствует плавному взаимодействию двух переменных. Если хотите, вы можете заменить gam моделью Лесса: mod <- loess(qsec ~ hp*wt, data=mtcars) и остальная часть кода будет работать так, как задумано. Я думаю, что вывод из этого, однако, заключается в том, что для построения гладкой поверхности вам нужно подогнать модель к данным.

3. могу ли я добавить формулу в функцию лесса, как мы обычно делаем в 2D-данных, например, mod <- loess(formula = y~ poly(x, 4, raw = TRUE), data = s) . Работает ли это и для 3D-данных, чтобы получить подгонку поверхности, mod <- loess(формула = z ~ poly(x, y, 4,5, raw = TRUE), data = s)

4. Возможно, но если вам нужен многочлен, я бы просто использовал lm(z~poly(x, 4, raw=TRUE) poly(y, 5, raw=TRUE), data=s) . Опять же, тогда остальная часть функции должна работать должным образом. Это создало бы аддитивную модель в x и y , но она была бы гладкой и нелинейной.