Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using D3.js with Shiny in Python #932

Open
tomicapretto opened this issue Dec 21, 2023 · 4 comments
Open

Using D3.js with Shiny in Python #932

tomicapretto opened this issue Dec 21, 2023 · 4 comments

Comments

@tomicapretto
Copy link

This is more a question than an issue (sorry if this is the wrong place!). I've been using Shiny in R a lot. In the past I used the package {r2d3} to include D3.js visualizations in my Shiny apps.

  • Does it exist a similar library in the Python world?
  • Is it possible to embed D3.js visualizations in Shiny for Python?

Thanks in advance!

@jcheng5
Copy link
Collaborator

jcheng5 commented Dec 22, 2023

Hi! I don't know of a similar library in the Python world. The easiest way to connect d3.js and Shiny right now is probably https://anywidget.dev/, which can be used with Shiny via the shinywidgets package.

(Unfortunately, the below example doesn't work with shinylive.io, or I would've linked you to a live demo; something within anywidgets and/or shinywidgets is asking where on disk the Shiny app lives, and shinylive.io doesn't have an answer.)

import anywidget
import traitlets
from shinywidgets import output_widget, render_widget

from shiny import App, render, ui


class D3PlotWidget(anywidget.AnyWidget):
    _esm = """
    import * as d3 from "https://esm.sh/d3@7";

    export function render({ model, el }) {
      // Declare the chart dimensions and margins.
      const width = 640;
      const height = 400;
      const marginTop = 20;
      const marginRight = 20;
      const marginBottom = 30;
      const marginLeft = 40;

      // Declare the x (horizontal position) scale.
      const x = d3.scaleUtc()
          .domain([new Date(model.get("startDate")), new Date(model.get("endDate"))])
          .range([marginLeft, width - marginRight]);

      // Declare the y (vertical position) scale.
      const y = d3.scaleLinear()
          .domain([0, 100])
          .range([height - marginBottom, marginTop]);

      // Create the SVG container.
      const svg = d3.create("svg")
          .attr("width", width)
          .attr("height", height);

      // Add the x-axis.
      svg.append("g")
          .attr("transform", `translate(0,${height - marginBottom})`)
          .call(d3.axisBottom(x));

      // Add the y-axis.
      svg.append("g")
          .attr("transform", `translate(${marginLeft},0)`)
          .call(d3.axisLeft(y));

      svg.classed("d3-plot-widget", true)

      // Return the SVG element.
      el.appendChild(svg.node());
    }
    """
    _css = """
    .d3-plot-widget { border: 1px solid #ea580c; }
    """
    startDate = traitlets.Unicode("2023-01-01").tag(sync=True)
    endDate = traitlets.Unicode("2024-01-01").tag(sync=True)


app_ui = ui.page_fluid(
    ui.input_date_range("dates", "Date range", start="2023-01-01", end="2024-01-01"),
    output_widget("widget"),
)


def server(input, output, session):
    @render_widget
    def widget():
        d3plot = D3PlotWidget()
        d3plot.startDate = input.dates()[0].strftime("%Y-%m-%d")
        d3plot.endDate = input.dates()[1].strftime("%Y-%m-%d")
        return d3plot


app = App(app_ui, server)

@tomicapretto
Copy link
Author

@jcheng5 thank you very much! I think this is already what I needed. I'll try to use it for the app I'm developing (I was working on it using R Shiny and r2d2) and if you want I can report back. In the meantime, feel free to close the issue or leave it open, as you consider. Thanks again!

@crazycapivara
Copy link

@tomicapretto Maybe shinyobservable with docs here is also useful for your usecase.

@tomicapretto
Copy link
Author

Thank you for the reference @crazycapivara! For my use case, I was trying to do some 3d visualization and discovered d3 is not good for that. I ended up using {rgl} and {shiny} in R. I you're interested I can point you to the app once it's public :).
The app is about sampling from 2d distributions using hamiltonian monte carlo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants