Я хочу нарисовать гистограмму с двумя столбцами рядом для каждой категории (LETTERS
) и добавить горизонтальную линию к каждому столбцу (y_ref
в виде красных линий и z_ref
в виде зеленых линий). Это должно выглядеть так:
Я попробовал это с 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
баров.
Вы должны использовать 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)
Да, я только что понял это. Справа это 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 баров).
Я полагаю, вы имеете в виду другое количество
shapes
? Если да, то обязательно. На самом деле они не привязаны к столбцу; они просто отображаются таким образом в этом ответе.