R Plotly Bar Chart — добавить маркеры горизонтальных линий

Я хочу нарисовать гистограмму с двумя столбцами рядом для каждой категории (LETTERS) и добавить горизонтальную линию к каждому столбцу (y_ref в виде красных линий и z_ref в виде зеленых линий). Это должно выглядеть так:

R Plotly Bar Chart — добавить маркеры горизонтальных линий

Я попробовал это с add_trace (и add_lines, add_segment и т. д.), но не могу найти правильный способ заставить его работать. Вот один из репрексов, которые я пробовал до сих пор.

df <- tibble(x = LETTERS[1:5], y = runif (5), z = runif (5), y_ref = runif (5), z_ref = runif (5))

plot_ly(
  df,
  x = ~x,
  y = ~y,
  type = "bar",
  name = "a"
) %>% add_trace(
  y = ~z, 
  name = "b"
) %>% layout(
  legend = list(
    orientation = "h"
  )
) %>% add_trace(
  y = ~y_ref, 
  type = 'scatter', 
  mode = 'lines',
  marker = list(
    line = list(
      width = 2,
      color = "red"
    )
  )
) %>% add_trace(
  y = ~z_ref, 
  type = 'scatter', 
  mode = 'lines',
  marker = list(
    line = list(
      width = 2,
      color = "green"
    )
  )
)

Обновлено: мне нужно решение для n баров.

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
38
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы должны использовать shapes для сегментов линий в Plotly. Кроме того, поскольку ось X является дискретной, x для фигур должно быть в paper пространстве.

При работе в бумажном пространстве вы используете график domain, чтобы вычислить значения для x. Plotly имеет значение по умолчанию domain, установленное на [0, 1] как для осей x, так и для осей y.

Между стержнями есть зазор; это тоже надо учитывать. Я использовал три функции для создания сегментов линии, используя всю эту информацию.

Наконец, я использовал seed для повторяемости.

Библиотеки, семена и базовый сюжет

library(tidyverse)
library(plotly)

set.seed(8)
df <- tibble(x = LETTERS[1:5], y = runif (5), z = runif (5),
             y_ref = runif (5), z_ref = runif (5))

p = plot_ly(df, x = ~x, y = ~y,
        type = "bar", name = "a") %>% 
  add_trace(y = ~z, name = "b") 

Создайте сегменты

# standard shape elements, call for color
details <- function(col){
  list(type = 'line',
       line = list(color = col),
       xref = "paper", yref = "y")
}
# green lines for orange bars
segs = lapply(1:nrow(df),
              function(k){
                x1 <- (k + k)/10 - .02  # if the domain is [0, 1]
                x0 <- x1 - .08
                y0 <- y1 <- df[k, ]$z_ref
                line = list("x0" = x0, "x1" = x1,
                            "y0" = y0, "y1" = y1)
                deets = details("green")
                c(deets, line)
              })
# green lines for blue bars
segs2 = lapply(1:nrow(df),
               function(j){
                 x1 <- (j + j - 1)/10  # if the domain is [0, 1]
                 x0 <- x1 - .08
                 y0 <- y1 <- df[j, ]$y_ref
                 line = list("x0" = x0, "x1" = x1,
                             "y0" = y0, "y1" = y1)
                 deets = details("red")
                 c(deets, line)
               })
segs = append(segs, segs2)

Собери это вместе

p %>% layout(legend = list(orientation = "h"),
             shapes = segs) 

Я полагаю, вы имеете в виду другое количество shapes? Если да, то обязательно. На самом деле они не привязаны к столбцу; они просто отображаются таким образом в этом ответе.

Kat 06.05.2022 16:07

Да, я только что понял это. Справа это x1 = (k + k)/(2*n) - (1/(10*n)) и x0 = (1/(2.5*n)), слева это x1 = (j + j - 1)/(2*n) и x0 = x1 - (1/(2.5*n)). (Кстати, я случайно удалил свой предыдущий комментарий, где я просил общее решение для n баров).

sedsiv 06.05.2022 16:24

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