<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/plotly-4-7-1-now-on-cran/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://moderndata.plot.ly/plotly-4-7-1-now-on-cran/"> R – Modern Data</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>I’m excited to announce that plotly 4.7.1 is now on CRAN! Along with some important bug fixes and numerous improvements to the underlying plotly.js library, this release includes an exciting new R-specific feature — the ability to <em>modify</em> (i.e., update without a full redraw) an existing plotly graph inside a shiny app via the new <code>plotlyProxy()</code> function. In other words, this proxy interface allows one to perform more efficient and responsive updates to a plotly graph within a shiny app. Before I provide an overview of the proxy interface, lets jump right into some of new plotly.js goodies.</p>
<div>
<h2>New plotly.js goodies</h2>
<p>Upgrading the R package from 4.7.0 to 4.7.1 upgrades the corresponding plotly.js version from 1.27.1 to 1.29.2. A number of exciting improvements have been added, just to name a few: select/lasso events for scattergl/scattermapbox trace types, 3D annotations, contour labelling, and even touch events on mobile. For quite a while now, R users have been able to <a rel="nofollow" href="https://plotly-book.cpsievert.me/linking-views-without-shiny.html" target="_blank">link multiple views (without shiny)</a> using nearly any (SVG) trace type (e.g., scatter, bar, heatmap, etc), but the new brush events on scattergl/scattermapbox trace types allow us to brush way more points and trigger selections via a map. Here is an example of highlighting earthquakes west of Fiji to compare the relative frequency of their magnitude and number of reporting stations (to the overall relative frequency):</p>
<div align="center">
<p><img src="https://i2.wp.com/i.imgur.com/l61zu6R.gif?resize=456%2C203" data-recalc-dims="1"></p>
</div>
<p>And the R code to generate the (self-contained!) HTML:</p>

<pre>library(crosstalk)
eqs &lt;- SharedData$new(quakes)

# you need a mapbox API key to use plot_mapbox()
# https://www.mapbox.com/signup/?route-to=https://www.mapbox.com/studio/account/tokens/
map &lt;- plot_mapbox(eqs, x = ~long, y = ~lat) %>%
  add_markers(color = ~depth) %>%
  layout(
    mapbox = list(
      zoom = 2,
      center = list(lon = ~mean(long), lat = ~mean(lat))
    )
  ) %>%
  highlight(&quot;plotly_selected&quot;)

# shared properties of the two histograms
hist_base &lt;- plot_ly(eqs, color = I(&quot;black&quot;), histnorm = &quot;probability density&quot;) %>%
  layout(barmode = &quot;overlay&quot;, showlegend = FALSE) %>%
  highlight(selected = attrs_selected(opacity = 0.5))

histograms &lt;- subplot(
  add_histogram(hist_base, x = ~mag),
  add_histogram(hist_base, x = ~stations),
  nrows = 2, titleX = TRUE
)

bscols(histograms, map)</pre>

<p>Another super cool and easy-to-use plotly.js feature is contour line labelling:</p>

<pre>plot_ly(z = volcano, type = &quot;contour&quot;, contours = list(showlabels = TRUE)) %>%
  colorbar(title = &quot;Elevation \n in meters&quot;)</pre>
<p><iframe src="https://plot.ly/~cpsievert/21126/.embed" width="100%" height="400"><br>
</iframe></p>
<p>To learn more about all the new plotly.js improvements, read the plotly.js <a rel="nofollow" href="https://github.com/plotly/plotly.js" target="_blank">release notes</a>.</p>
</div>
<div>
<h2>Modifying plotly graphs via <code>plotlyProxy()</code></h2>
<p>The design of <strong>plotly</strong>‘s new proxy interface is inspired by similar interfaces in <strong>leaflet</strong> and <strong>DT</strong> (thanks Joe Cheng and Yihui Xie!). That is, <code>plotlyProxy()</code> initiates a proxy object just like <code>leafletProxy()</code>/<code>dataTableProxy()</code> by referencing a shiny output ID. However, at least for now, you <em>must</em> use the <code>plotlyProxyInvoke()</code> function to modify a <code>plotlyProxy()</code> object, which requires knowledge/use of a <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/" target="_blank">plotly.js method</a> for the updating logic (among them, <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/#plotlyrestyle" target="_blank">Plotly.restyle</a>, <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/#plotlyrelayout" target="_blank">Plotly.relayout</a>, <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/#plotlyaddtraces" target="_blank">Plotly.addTraces</a>, and <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/#plotlydeletetraces" target="_blank">Plotly.deleteTraces</a> are the most widely useful). This simple shiny app uses <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/#plotlyrestyle" target="_blank">Plotly.restyle</a> to change the fillcolor of Canada (i.e., polygons) in response to the dropdown.</p>
<div align="center">
<p><img src="https://i2.wp.com/i.imgur.com/PzDMqZ0.gif?resize=456%2C228" data-recalc-dims="1"></p>
</div>
<p>Notice how the map and the outline of Canada are not effected (i.e., are not redrawn) when the fill color changes. The code for the app is below. Notice how, instead of having <code>renderPlotly()</code> regenerate the map in response to a change in <code>input$color</code> (i.e., the “old” or “naive” way of updating a plotly graph which always uses <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/#plotlynewplot" target="_blank">Plotly.newPlot</a>), it uses <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/#plotlyrestyle" target="_blank">Plotly.restyle</a> via <code>plotlyProxyInvoke()</code> to perform a more efficient update.</p>

<pre># you can also run this example via the new plotly_example() function!
# plotly_example(&quot;shiny&quot;, &quot;proxy_restyle_canada&quot;)

library(shiny)
library(plotly)

ui &lt;- fluidPage(
  selectInput(&quot;color&quot;, &quot;Canada's fillcolor&quot;, colors(), selected = &quot;black&quot;),
  plotlyOutput(&quot;map&quot;)
)

server &lt;- function(input, output, session) {
  
  output$map &lt;- renderPlotly({
    map_data(&quot;world&quot;, &quot;canada&quot;) %>%
      group_by(group) %>%
      plot_mapbox(x = ~long, y = ~lat, color = I(&quot;black&quot;)) %>%
      add_polygons() %>%
      layout(
        mapbox = list(center = list(lat = ~median(lat), lon = ~median(long)))
      )
  })
  
  observeEvent(input$color, {
    plotlyProxy(&quot;map&quot;, session) %>%
      plotlyProxyInvoke(&quot;restyle&quot;, list(fillcolor = toRGB(input$color)))
  })
  
}

shinyApp(ui, server)</pre>

<p>It’s worth noting that using <code>plotlyProxyInvoke()</code> requires knowledge of the <a rel="nofollow" href="https://plot.ly/r/reference/" target="_blank">figure reference</a> and the <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/" target="_blank">plotly.js API</a>. Thus, it can help to have some knowledge of how your plots are actually represented in JSON, which you can always obtain via <code>plotly_json()</code>, for example:</p>

<pre>p &lt;- plot_ly(economics, x = ~pce, y = ~psavert, z = ~unemploy, color = ~as.numeric(date), mode = &quot;markers+lines&quot;)
plotly_json(p)</pre>

<div align="center">
<p><img src="https://i2.wp.com/i.imgur.com/7VQUsxC.gif?resize=456%2C228" data-recalc-dims="1"></p>
</div>
<p>This gives us a glimpse into what the R package actually sends along to the <a rel="nofollow" href="https://plot.ly/javascript/plotlyjs-function-reference/#plotlyplot" target="_blank">newPlot method</a> to generate the initial view on page load. In this case, the R package generates scatter3d <a rel="nofollow" href="https://plot.ly/r/reference/#scatter3d-marker" target="_blank">marker</a> and <a rel="nofollow" href="https://plot.ly/r/reference/#scatter3d-line" target="_blank">line</a> objects. We could use a similar <code>plotlyProxyInvoke()</code> pattern as before to alter the value of certain attribute(s) of these objects (e.g., marker/line size/width):</p>
<div align="center">
<p><img src="https://i0.wp.com/i.imgur.com/jXLW2fz.gif?resize=456%2C228" data-recalc-dims="1"></p>
</div>
<pre># you can also run this example via the new plotly_example() function!
# plotly_example(&quot;shiny&quot;, &quot;proxy_restyle_economics&quot;)

library(shiny)
library(plotly)

ui &lt;- fluidPage(
  sliderInput(&quot;marker&quot;, &quot;Marker size&quot;, min = 0, max = 20, value = 8),
  sliderInput(&quot;path&quot;, &quot;Path size&quot;, min = 0, max = 30, value = 2),
  plotlyOutput(&quot;p&quot;)
)

server &lt;- function(input, output, session) {
  
  output$p &lt;- renderPlotly({
    plot_ly(
      economics, x = ~pce, y = ~psavert, z = ~unemploy, 
      color = ~as.numeric(date), mode = &quot;markers+lines&quot;
    )
  })
  
  observeEvent(input$marker, {
    plotlyProxy(&quot;p&quot;, session) %>%
      plotlyProxyInvoke(
        &quot;restyle&quot;, 
        # could also do list(marker = list(size = input$marker))
        # but that overwrites the existing marker definition
        # https://github.com/plotly/plotly.js/issues/1866#issuecomment-314115744
        list(marker.size = input$marker)
      )
  })
  
  observeEvent(input$path, {
    plotlyProxy(&quot;p&quot;, session) %>%
      plotlyProxyInvoke(
        &quot;restyle&quot;, list(line.width = input$path)
      )
  })
  
}

shinyApp(ui, server)</pre>

<p>At this point, you might be wondering something along these lines of: “how on earth am I supposed to know/remember what attributes a scatter3d line object has?” One option is to search through the figure reference, but I prefer to use the <code>schema()</code> function since it allows me to more easily traverse the reference and get more information about acceptable/default attribute values. For example, when creating this app, I forgot what line attribute controlled its size/width, so I did the following:</p>
<div align="center">
<p><img src="https://i0.wp.com/i.imgur.com/vk4FxLI.gif?resize=456%2C228" data-recalc-dims="1"></p>
</div>
<p>I hope you find this new release useful and this post informative for creating more performant shiny apps! If you’re interested in seeing more examples of <code>plotlyProxy()</code> in action, see <a rel="nofollow" href="https://github.com/ropensci/plotly/blob/master/inst/examples/shiny/" target="_blank">here</a>.</p>
</div>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://moderndata.plot.ly/plotly-4-7-1-now-on-cran/"> R – Modern Data</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/XWnf7v_J0Mc" height="1"></a></div>