Можно ли объединить легенду ggplot с легендой заговора, чтобы они были эквивалентны? - PullRequest
1 голос
/ 20 апреля 2020

Я пытаюсь объединить ggplot и plotly вместе, чтобы создать временную шкалу.

Работает отлично, но есть проблема с использованием легенды. Код ниже повторяет то, что я пытаюсь сделать.

library(ggplot2)
library(plotly)
x=1:10
df2 = data.frame(x,y = 2*x+rnorm(length(x)),lab = as.factor(c("col1","col2")))
status_colors <- c("#0070C0", "#00B050", "#FFC000", "#C00000","darkgreen","purple","darkgrey","blue","salmon","darkorange","black","navy","darkblue")
status_levels <- c(sort(unique(df2$lab))) 

p= ggplot(df2,aes(x=x, y=y, col = lab)) + geom_point() + labs(col="labtest") +
  scale_color_manual(values=status_colors,
                     labels=status_levels, drop = FALSE)

fig = ggplotly(p, tooltip = NULL)

fig %>%  
  add_text(
    x = df2$x,
    y = ifelse(df2$y>0,df2$y+0.05,df2$y-0.05),
    text = df2$lab,
    hovertext = df2$lab,
    hoverinfo = 'text',
    mode ="text",
    textfont = list(color=status_colors[df2$lab], size =10),
    marker = list(color=status_colors[df2$lab], size = 0.00001),
    showlegend = T,
    textposition = ifelse(df2$y>0,"top center","bottom center")
  )

Как видно на рисунке, метка каждой точки имеет тот же цвет, что и точка, к которой она прикреплена. Но всякий раз, когда я добавляю легенду для текста метки из сюжета, появляется новая легенда, которая контролирует все точки независимо от их цвета.

enter image description here

Таким образом, есть способ объединить легенду ggplot с легендой заговора так, чтобы она была только написана col1 и col2 с правильным цветом, и чтобы всякий раз, когда я взаимодействую с точками определенного цвета, прикрепленная к нему метка остается там?

Другими словами, есть ли способ удалить легенду "trace 2" и сделать "add_text" знаете, что в ggplot уже создана легенда?

1 Ответ

1 голос
/ 20 апреля 2020

Если я вас правильно понял, помимо избавления от второй легенды (которую можно просто достичь, установив showlegend = FALSE), вы хотите, чтобы одна легенда контролировала как точки, так и метки. Это может быть достигнуто через legendgroup с. Вместо добавления меток с одним add_text вы могли бы (или должны? Извините. Все еще заговорчиво новичок ie, так что, возможно, существует более простой подход) добавить метки с помощью двух add_text вызовов, по одному для каждого col. Вместо копирования и вставки (что, вероятно, хорошо только для двух столбцов, но с большим количеством столбцов ...) вы можете добавить их через маги c из purrr::reduce к объекту ggplotly. Попробуйте это:

library(ggplot2)
library(plotly)
library(purrr)

x=1:10
df2 = data.frame(x,y = 2*x+rnorm(length(x)),lab = as.factor(c("col1","col2")))
status_colors <- c("#0070C0", "#00B050", "#FFC000", "#C00000","darkgreen","purple","darkgrey","blue","salmon","darkorange","black","navy","darkblue")
status_levels <- c(sort(unique(df2$lab))) 

p= ggplot(df2,aes(x=x, y=y, col = lab)) + geom_point() + 
  labs(col="labtest") +
  scale_color_manual(values=status_colors,
                     labels=status_levels, drop = FALSE)

fig = ggplotly(p, tooltip = NULL)

purrr::reduce(c("col1", "col2"), ~ .x %>% add_text(
    data = filter(df2, lab == .y),
    x = ~x,
    y = ~ifelse(y > 0, y + 0.05, y-0.05),
    text = ~lab,
    hovertext = ~lab,
    hoverinfo = 'text',
    mode ="text",
    textfont = list(color= ~status_colors[lab], size =10),
    marker = list(color= ~status_colors[lab], size = 0.00001),
    showlegend = FALSE,
    textposition = ~ifelse(y>0, "top center","bottom center"),
    legendgroup = .y
  ), .init = fig) 

Кстати: я также немного упростил код. Вам не нужно df2$..., потому что (gg)plotly уже знает данные.

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...