Как сгруппировать трехмерные линейные графики по двум факторам с помощью пакета Plotly в R?

Я проверил официальную веб-страницу Plotly, но как построить следующую задачу все еще ускользает от меня:

id <- c(rep(1,5), rep(2,5), rep(3,5), rep(4,5))
t <- rep(seq(50,75,length.out=5), 4)
x <- runif(20) + sin(t) 
y <- rnorm(20) + cos(t)
gender <- c(rep("F",10), rep("M",10))
smoke <- c(rep("Y",5), rep("N",10), rep("Y",5))

DATA <- data.frame(ID, t, x, y, gender, smoke)

fig <- plot_ly(DATA, x = ~t, y = ~y, z = ~x, .......)

Предположим, у меня есть 4 группы пациентов (сгруппированных по 2 факторам: женщины / мужчины и курильщики / некурящие), каждая из которых связана с 5 наблюдениями $ (x_i, y_i) $ с отметками времени $ t_i $. Поэтому мне нужно нарисовать трехмерный линейный график $$ {(t_i, x_i, y_i)} _ {i = 1} ^ {i = 5} $ для каждого пациента, но все на одном холсте. Если я хочу обозначить полы красным / синим цветом, курильщиков - твердыми и некурящими - пунктирными линиями и указать их в легенде, что мне делать (в идеале, используя R)?


person Paw in Data    schedule 17.04.2020    source источник


Ответы (1)


Заданный вами вид трехмерного сюжета может быть получен следующим образом:

library(plotly)

id <- c(rep(1,5), rep(2,5), rep(3,5), rep(4,5))
t <- rep(seq(50,75,length.out=5), 4)
x <- runif(20) + sin(t) 
y <- rnorm(20) + cos(t)
gender <- c(rep("F",10), rep("M",10))
smoke <- c(rep("Y",5), rep("N",10), rep("Y",5))

DATA <- data.frame(id, t, x, y, gender, smoke)

col_gender <- c(M = "red", F = "blue")
lt_smoke <- c(Y = "solid", N = "dash")
sym_id <- c(`1` = "circle", `2` = "square", `3` = "diamond", `4` = "cross")

fig <- plot_ly(DATA, 
               x = ~x, y = ~y, z = ~t, symbol = ~id, color = ~gender, linetype = ~smoke, type = 'scatter3d', mode = 'lines+markers',
               line = list(width = 6),
               marker = list(size = 3.5, cmin = -20, cmax = 50),
               colors = col_gender,
               linetypes = lt_smoke,
               symbols = sym_id)
fig

Редактировать:

В случае большего количества пациентов лучший вариант - отобразить id по цвету и дополнительно сгруппировать по id с помощью преобразования groupby

library(plotly)

id <- c(rep(1,5), rep(2,5), rep(3,5), rep(4,5), rep(5,5), rep(6,5), rep(7,5), rep(8,5))
t <- rep(seq(50,75,length.out=5), 8)
x <- runif(40) + sin(t) 
y <- rnorm(40) + cos(t)
gender <- c(rep("F",10), rep("M",10), rep("F",10), rep("M",10))
smoke <- c(rep("Y",5), rep("N",10), rep("Y",5), rep("Y",5), rep("N",10), rep("Y",5))

lt_smoke <- c(Y = "solid", N = "dash")
sym_id <- c(M = "circle", F = "square")

fig <- plot_ly(DATA, 
               x = ~x, y = ~y, z = ~t, symbol = ~gender, color = ~id, linetype = ~smoke, type = 'scatter3d', mode = 'lines+markers',
               line = list(width = 6),
               marker = list(size = 3.5, cmin = -20, cmax = 50),
               linetypes = lt_smoke,
               symbols = sym_id,
               transforms = list(
                 list(
                   type = 'groupby',
                   groups = ~id)
               ))
fig
person stefan    schedule 17.04.2020
comment
Спасибо! Но рисует ли он отдельный трехмерный линейный график для каждого пациента (он же для каждых 5 наблюдений)? Я ожидал id участие или add = TRUE где-то. - person Paw in Data; 19.04.2020
comment
Привет. И извините. Я прочитал часть с идентификатором в вашем вопросе. (: В общем: нет разных строк для пациентов. Данные сгруппированы только по комбинациям пола и дыма. В этом смысле на графике есть разные линии для 4 идентификаторов, приведенных в примере данных. Для явной группировки по идентификатору один подход будет быть для сопоставления идентификатора, например, символа, который приводит к разным типам маркеров.Однако, по крайней мере, для данных примера это не имеет никакого значения.Но если у вас больше групп пациентов, это, вероятно, будет. - person stefan; 19.04.2020
comment
Привет спасибо! Я знаю, что в моем посте много вопросов ^ _ ^ - person Paw in Data; 19.04.2020
comment
На самом деле у меня 60 пациентов, и причина, по которой я хочу добавлять данные пациента за пациентом вместо сопоставления идентификатора с символами, заключается в том, что (1) 60 символов - это слишком много (2) каждый линейный график должен отражать развитие событий для каждого пациента, поэтому мне нужно избавиться от отрезка линии между 5-м и 6-м, 10-м и 11-м ... точками данных. Лучшее, что я могу придумать, - это начать все сначала. Вы знаете, как это сделать? Или с Plotly это невозможно? - person Paw in Data; 01.05.2020
comment
Ага. В этом случае сопоставление идентификатора символам невозможно. ИМХО, лучший и самый простой вариант в этом случае - сопоставить идентификатор по цвету и вместо этого сопоставить пол по символу. - person stefan; 01.05.2020
comment
Да, тогда все еще существует проблема с отрезанием отрезков линии между пациентами. - person Paw in Data; 01.05.2020
comment
Привет. Только что добавил правку. Пришлось добавить больше пациентов к данным, чтобы понять вашу точку зрения. Хитрость заключается в том, чтобы сгруппировать данные по идентификатору, что может быть достигнуто с помощью преобразования типа groupby. - person stefan; 01.05.2020
comment
О, это умно. Спасибо! Но почему два list() справа от transforms? - person Paw in Data; 01.05.2020