Я пытаюсь получить доступ к plotly_build реактивного графика, чтобы вручную отредактировать стандартные компоненты графика для дальнейшей настройки моего графика. Я могу сделать это простым сценарием .R, чтобы проверить функциональность изменений в сборке, но мне не удалось заставить его работать в R Shiny, который я создаю, и который включает реактивный сюжет.
Вкладка на включенной Shiny включает в себя selectizeInput () для функции, которую выбирает пользователь, которую Shiny использует для фильтрации фрейма данных и создания графика соответствующим образом. При этом графики стали немного запутанными как на ggplot, так и на графике (используя ggplotly для преобразования в сюжет). В конечном итоге я настроил ggplot настолько, насколько мог, но с помощью plotly_build () я вручную получил доступ к компонентам plotly, чтобы отредактировать такие вещи, как метки легенды и заголовок.
При тестировании вне Shiny я смог создать этот график, вручную изменив функцию фильтра. В Shiny, однако, поскольку есть пользовательский ввод, который управляет реактивным сюжетом, это создало огромный каскад проблем.
Вот упрощенный пример моей попытки:
library(shiny)
library(dplyr)
library(readr)
library(ggplot2)
library(plotly)
library(scales)
library(kableExtra)
ui <- fluidPage(
# Application title
titlePanel("DASHBOARD TITLE"),
mainPanel(
tabsetPanel(
tabPanel("DATA PLOTS",
selectizeInput("srvr", label = "Name", choices=NULL, options = list(placeholder = 'Search for a Name')),
plotlyOutput("entrance_exit_npl_plotly"))
)
)
)
server <- function(input, output, session) {
entrance_exit_table_npl <- readRDS(file='path/filename.rds')
updateSelectizeInput(session, 'srvr', choices = c(unique(entrance_exit_table_npl$ENTITYNM)), selected = 'DEFAULT OPTION',server = TRUE)
# Storing user input$srvr
selected_srvr <- reactive({as.character(input$srvr)})
# Filtering based on user input
servicer_data_npl <- reactive({
filter(entrance_exit_table_npl, ENTITYNM==selected_srvr()) %>%
group_by(P_ENTITY, LN_CURR_ACVY_STRT_DT) %>%
select(contains("upb"))})
# Creating ggplot object and attempt to capture plotly_build
plot_servicer_build <- reactive({
plotly_build(
ggplot(servicer_data_npl(), aes(LN_CURR_ACVY_STRT_DT)) +
geom_line(aes(y=new_npl_entrance_upb, color = 'green', linetype = 'dotted')) +
geom_line(aes(y=from_rpl_entrance_upb, color = 'green',linetype = 'dashed')) +
geom_line(aes(y=total_entrance_upb, color = 'green', linetype = 'solid')) +
geom_line(aes(y=npl_liqd_exit_upb, color = 'red', linetype = 'dotted')) +
geom_line(aes(y=to_rpl_exit_upb, color = 'red', linetype = 'dashed')) +
geom_line(aes(y=total_npl_exit_upb, color = 'red', linetype = 'solid')) +
geom_line(aes(y=total_npl_upb, color = 'blue', linetype = 'dotdash')) +
scale_y_continuous("UPB (Millions)",
labels = unit_format(unit = "M", big.mark = ",")) +
scale_x_date("Activity Month",
breaks = date_breaks("1 month"),
date_labels = "%b-%Y",
expand = c(0,0)) +
theme(plot.title = element_text(hjust = 0.5),
axis.text.x = element_text(angle = 45)) +
ggtitle(paste(selected_srvr(),"NPL Entrance and Exits")) +
scale_color_identity(guide='legend') +
scale_linetype_identity(guide='legend')
)
})
# Editing plotly build. What I would like to happen, but will not work. This could also use the $ notation for subsetting, but this is how I did it to the plotly_build() list object outside of the Shiny. First, editing legend entry names, and second, removing the title of the legend.
# plot_servicer_build[["x"]][["data"]][[1]][["name"]] <- "Entry Name 1"
# plot_servicer_build[["x"]][["data"]][[2]][["name"]] <- "Entry Name 2"
# plot_servicer_build[["x"]][["data"]][[3]][["name"]] <- "Entry Name 3"
# plot_servicer_build[["x"]][["data"]][[4]][["name"]] <- "Entry Name 4"
# plot_servicer_build[["x"]][["data"]][[5]][["name"]] <- "Entry Name 5"
# plot_servicer_build[["x"]][["data"]][[6]][["name"]] <- "Entry Name 6"
# plot_servicer_build[["x"]][["data"]][[7]][["name"]] <- "Entry Name 7"
# plot_servicer_build[["x"]][["layout"]][["annotations"]][[1]][["text"]] <- " "
# This was an attempt to subset a data frame resulting from a reactive function. I figured it wouldn't work, but I had seen stackoverflow posts where this was possible!
# plot_servicer_build()$x$layout$annotations[[1]]$text <- " "
# Output plotly rendering of graph and edit hover info
output$entrance_exit_npl_plotly <- renderPlotly(
ggplotly(plot_servicer_build()) %>%
style(hovertemplate = "Date: %{x} <br>UPB: $%{y}M"))
}
shinyApp(ui = ui, server = server)
Несколько проблем, с которыми я столкнулся:
- Я не могу добавить другие строкикода, не привязанного к цепочке, присутствующей в renderPlotly (), так же, как и многие посты, которые я видел в своем исследовании. Мой требует запятую между каждой командой add, и это не поможет:
- Мне вообще не удается получить доступ к объекту списка plotly_build ()
- Подстановка реактивного объекта кажется довольно сложной.
Это ошибка, с которой я столкнулся при попытке использовать первоначальный синтаксис поднабора с помощью [[]], что я могу сделать за пределами Shiny (без реактивности):
Warning: Error in $: object of type 'closure' is not subsettable
Когда я пытаюсь использовать второй метод подмножества plot_servicer_build ():
Error in plot_servicer()$x$layout$annotations[[1]]$text <- " " :
invalid (NULL) left side of assignment
На этом пути было несколько других ошибок!
Есть ли кто-нибудь у кого есть предложения о том, как я могу внести эти изменения в plotly_build реактивного объекта ?! Я потратил так много времени на это, и мне кажется, что я становлюсь ближе, когда я пробую некоторые немного многообещающие методы в Интернете для подобных задач (например, plotyProxy ()), и я очень полон решимости получить этоработать, особенно потому, что я знаю, что код работает за пределами реактивного сюжета в Shiny! Я приветствую все и любые ваши мысли. Я прошу прощения за то, что не предоставил набор данных, но он запатентован, поэтому я должен быть осторожен.
Версии:
- RStudio: 1.2.5001.3
- Графика: 4.9.0 dev
- Shiny: 1.3. 2
- ggplot2: 3.1.1
- R: 3.6.0
Спасибо!