Как оптимизировать положение заголовков и представления данных по оси Y?

Как я могу в сюжетном сюжете: а) расположить названия осей горизонтально над соответствующими осями? б) уменьшить расстояние между 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
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
83
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Попробуйте 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')

Ответ принят как подходящий

Вы сказали, что ищете три вещи:

  • названия осей горизонтальные, над каждой осью
  • уменьшить отступы (сохраняя пространство между осями Y)
  • добавлять баллы на основе критериев

Названия осей как аннотации

Чтобы добавить заголовки осей сверху, необходимо выполнить три основных шага:

  • удалить заголовки из текущего макета и добавить shift к оси «y2»
  • создавать аннотации
  • вызовите обновленную версиюplotly.js(зависимость, которая работает в фоновом режиме)

Новый пример макета с удалением заголовков (полный код будет предоставлен чуть позже, это лишь небольшая часть, чтобы показать вам, что происходит.

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?) беспокоит.

Gurkenhals 12.07.2024 09:52

Другие вопросы по теме