Как я могу в сюжетном сюжете: а) расположить названия осей горизонтально над соответствующими осями? б) уменьшить расстояние между y=0 и осью X? в) нарисуйте зеленые точки данных для мощности до увеличения и после уменьшения (при y=0) такой же толщины, как зеленые точки данных, где y>0?
Я был бы очень признателен за вашу поддержку.
library(plotly)
# Sample data
d <- data.frame(
time = seq(1, 600, by = 1),
VO2 = c(rnorm(120, 250, 10), rnorm(120, 300, 15), seq(300, 2000, length.out = 240), rnorm(120, 300, 15)),
VCO2 = c(rnorm(120, 200, 10), rnorm(120, 250, 15), seq(250, 1800, length.out = 240), rnorm(120, 250, 15)),
power = c(rep(0, 120), rep(0, 120), seq(0, 160, length.out = 240), rep(0, 120))
)
# Create the plot
fig <- plot_ly(data = d) %>%
add_lines(x = ~time, y = ~VO2,
line = list(color = 'blue'), name = "VO2") %>%
add_lines(x = ~time, y = ~VCO2, yaxis = "y2",
line = list(color = 'red'), name = "VCO2") %>%
add_lines(x = ~time, y = ~power, yaxis = "y3",
line = list(color = 'green'), name = "Power") %>%
layout(
xaxis = list(
title = list(text = 'Time [sec]', standoff = 10),
color = 'black',
showline = TRUE,
tickcolor = 'black',
tickwidth = 2,
linewidth = 2,
ticks = "outside"
),
yaxis = list(
title = list(text = 'VO2', standoff = 20),
showline = TRUE,
side = "left",
color = 'blue',
tickcolor = 'blue',
tickwidth = 2,
linewidth = 2,
ticks = "outside",
range = c(0, max(c(d$VO2, d$VCO2)))
),
yaxis2 = list(
title = list(text = 'VCO2', standoff = 20),
showline = TRUE,
overlaying = "y",
anchor = "free",
side = "left",
color = 'red',
tickcolor = 'red',
tickwidth = 2,
linewidth = 2,
ticks = "outside",
position = -0.1,
range = c(0, max(c(d$VO2, d$VCO2)))
),
yaxis3 = list(
title = list(text = 'Power', standoff = 20),
showline = TRUE,
overlaying = "y",
side = "right",
color = 'green',
tickcolor = 'green',
tickwidth = 2,
linewidth = 2,
ticks = "outside",
range = c(0, max(d$power) * 1.25)
),
showlegend = FALSE, # Removes legend
margin = list(pad = 50, b = 0, l = 100, r = 100)
)
fig
Попробуйте matplot
, умножьте столбец мощности на 10.
clr <- c('blue', 'red', 'darkgreen')
par(mar=c(4, 4.5, 2, 4.5))
matplot(t(t(d[-1])*c(1, 1, 10)), type='l', axes=FALSE, ann=FALSE, lty=1, col=clr)
box()
axis(1); axis(2, las=1); axis(4, axTicks(2), labels=axTicks(2)/10, col.axis=clr[3], col=clr[3], las=1)
mtext('Time [sec]', 1, 2.5); mtext('Volume', 2, 3); mtext('Power', 4, 3, col=clr[3])
legend('topleft', lty=1, col=clr, leg=c('VO2', 'VCO2', 'Power'), bty='n')
Вы сказали, что ищете три вещи:
Чтобы добавить заголовки осей сверху, необходимо выполнить три основных шага:
shift
к оси «y2»Новый пример макета с удалением заголовков (полный код будет предоставлен чуть позже, это лишь небольшая часть, чтобы показать вам, что происходит.
yaxis = list(
# title = list(text = 'VO2', standoff = 20), # remove title
title = '',
showline = TRUE,
Что касается сдвига, я немного угадал и проверил, поскольку график хотел перекрыть оси, когда я удалил отступы, я переместился y2
влево от y1
оси. Это если shift
в yaxis2 = ...
установлено на 70.
Остальные аспекты макета остаются такими, какими вы их закодировали в своем вопросе.
Когда я создавал аннотации, я использовал позиции x
, например, сдвиг, немного догадок и проверку визуальной эстетики. Я использовал цвета для заголовков, которые вы им назначили. Наконец, я установил размер шрифта 14. Это размер заголовка оси по умолчанию.
Большая часть контента, необходимого для создания аннотации, здесь идентична, поэтому я использовал lapply
для построения списка.
Это код, используемый для создания аннотаций:
xs <- c(-.095, -.2, 1.095) # x-axis positions
clr <- c("blue", "red", "green") # title colors
anno <- lapply(1:3, \(k) { # build new axis titles as annotations
if (names(d)[k + 1] != toupper(names(d)[k + 1])) { # take titles from dataframe
tlt = paste0(toupper(substring(names(d)[k + 1], 1, 1)), # capitalize if necessary
substring(names(d)[k + 1], 2, 1000))
} else {
tlt = names(d)[k + 1]
} # using paper space, on top of y axes, at variable x positions
list(xref = "paper", yref = "paper", x = xs[k], y = 1.1, showarrow = F,
font = list(color = clr[k], size = 14), text = tlt)
})
Содержимое anno
теперь можно назначить annotations
в сюжете layout
.
Наконец, shift
не будет работать без обновления серверной части Plotly.js. Чтобы обновить эту зависимость, я использовал следующую функцию.
fixer <- function(plt) {
# changes to dependency so that all code works
plt$dependencies[[5]]$src$file = NULL
plt$dependencies[[5]]$src$href = "https://cdn.plot.ly"
plt$dependencies[[5]]$script = "plotly-2.33.0.min.js"
plt$dependencies[[5]]$local = FALSE
plt$dependencies[[5]]$package = NULL
plt
}
Теперь, когда сдвиг работает, все, что вам нужно сделать, чтобы уменьшить отступы, — это уменьшить число, которое вы вызвали в layout(margin = list
.
Я не совсем уверен, что вы здесь хотите, но я интерпретировал это как маркеры для всех точек, в которых d$power == 0
. При этом при шестистах наблюдениях, даже когда точки огромны, это просто пятно, которое выглядит как толстая линия, пока вы не увеличите масштаб. Я предполагаю, что это просто данные для этого вопроса, а не данные, которые вы на самом деле используется, так что, возможно, эта информация будет более полезной в том контексте, в котором вы ее используете.
Чтобы добавить маркеры, вы можете добавить еще одну трассировку. Для этой трассировки необходимо определить, что она не использует те же данные, что и другие трассировки.
Вот код трассировки маркеров, который я использовал:
add_markers(inherit = F, data = d %>% filter(power == 0), # criteria for markers
x = ~time, y = ~power, yaxis = "y3",
marker = list(color = "green", size = 10), name = "")
Вот как выглядит график с этими изменениями (обратите внимание на пятно нулевой строки power
).
library(plotly)
# Sample data
d <- data.frame(
time = seq(1, 600, by = 1),
VO2 = c(rnorm(120, 250, 10), rnorm(120, 300, 15), seq(300, 2000, length.out = 240), rnorm(120, 300, 15)),
VCO2 = c(rnorm(120, 200, 10), rnorm(120, 250, 15), seq(250, 1800, length.out = 240), rnorm(120, 250, 15)),
power = c(rep(0, 120), rep(0, 120), seq(0, 160, length.out = 240), rep(0, 120))
)
fixer <- function(plt) {
# changes to dependency so that all code works
plt$dependencies[[5]]$src$file = NULL
plt$dependencies[[5]]$src$href = "https://cdn.plot.ly"
plt$dependencies[[5]]$script = "plotly-2.33.0.min.js"
plt$dependencies[[5]]$local = FALSE
plt$dependencies[[5]]$package = NULL
plt
}
# Create the plot
fig <- plot_ly(data = d) %>%
add_lines(x = ~time, y = ~VO2,
line = list(color = 'blue'), name = "VO2") %>%
add_lines(x = ~time, y = ~VCO2, yaxis = "y2",
line = list(color = 'red'), name = "VCO2") %>%
add_lines(x = ~time, y = ~power, yaxis = "y3",
line = list(color = 'green'), name = "Power") %>%
add_markers(inherit = F, data = d %>% filter(power == 0), # criteria for markers
x = ~time, y = ~power, yaxis = "y3",
marker = list(color = "green", size = 10), name = "") %>%
layout(
xaxis = list(
title = list(text = 'Time [sec]', standoff = 10), domain = c(0, 1),
color = 'black',
showline = TRUE,
tickcolor = 'black',
tickwidth = 2,
linewidth = 2,
ticks = "outside", zeroline = F
),
yaxis = list(
# title = list(text = 'VO2', standoff = 20),
title = '',
showline = TRUE,
side = "left",
color = 'blue',
tickcolor = 'blue',
tickwidth = 2,
linewidth = 2,
ticks = "outside",
range = c(0, max(c(d$VO2, d$VCO2)))
),
yaxis2 = list(
# title = list(text = 'VCO2', standoff = 20),
showline = TRUE,
overlaying = "y",
anchor = "free",
side = "left",
color = 'red',
tickcolor = 'red',
tickwidth = 2,
linewidth = 2,
ticks = "outside",
shift = -70,
# position = -0.1,
range = c(0, max(c(d$VO2, d$VCO2)))
),
yaxis3 = list(
# title = list(text = 'Power', standoff = 20),
showline = TRUE,
overlaying = "y",
side = "right",
color = 'green',
tickcolor = 'green',
tickwidth = 2,
linewidth = 2,
ticks = "outside",
range = c(0, max(d$power) * 1.25)
),
showlegend = FALSE, # Removes legend
# margin = list(pad = 50, b = 0, l = 100, r = 100)
margin = list(pad = 20, b = 0, l = 150, r = 100, t = 50)
)
xs <- c(-.095, -.2, 1.095) # x-axis positions
clr <- c("blue", "red", "green") # title colors
anno <- lapply(1:3, \(k) { # build new axis titles as annotations
if (names(d)[k + 1] != toupper(names(d)[k + 1])) { # take titles from dataframe
tlt = paste0(toupper(substring(names(d)[k + 1], 1, 1)), # capitalize if necessary
substring(names(d)[k + 1], 2, 1000))
} else {
tlt = names(d)[k + 1]
} # using paper space, on top of y axes, at variable x positions
list(xref = "paper", yref = "paper", x = xs[k], y = 1.1, showarrow = F,
font = list(color = clr[k], size = 14), text = tlt)
})
fig %>% layout(annotations = anno) %>% fixer() # create the plot!
Ух ты! Только тонкая зеленая линия (зеленая ось X?) беспокоит.