GithubHelp home page GithubHelp logo

residentmario / py_d3 Goto Github PK

View Code? Open in Web Editor NEW
450.0 23.0 40.0 6.45 MB

D3 block magic for Jupyter notebook.

License: MIT License

Python 81.27% Jupyter Notebook 18.73%
data-visualization d3 jupyter-notebook jupyter

py_d3's Introduction

py_d3 PyPi version t

Deprecation notice

The py_d3 package has been retired. This package was only ever intended to work in the classical Jupyter Notebook environment, this has been replaced pretty much all applications by the more advanced and more feature-complete Jupyter Lab. Jupyter Lab has a completely different SDK for notebook extensions, which this package neither uses nor supports.

As such this package is now unmaintained.

For users looking for an interactive environment for building D3.JS visualizations in, I recommend Observable Notebooks.

For users looking to embed D3.JS visualizations in their Jupyter Lab notebooks, check out this Gist.

Happy plotting!

About

py_d3 is an IPython extension which adds D3 support to the Jupyter Notebook environment.

D3 is a powerful JavaScript data visualization library, while Jupyter is an intuitive browser-hosted Python development environment. Wouldn't it be great if you could use them together? Now you can.

Quickstart

You can install py_d3 by running pip install py_d3. Then load it into a Jupyter notebook by running%load_ext py_d3.

Use the %%d3 cell magic to define notebook cells with D3 content.

alt text

py_d3 allows you to express even very complex visual ideas within a Jupyter Notebook without much difficulty. A Radial Reingold-Tilford Tree, for example:

alt text

An interactive treemap (original):

alt text

Or even the entire D3 Show Reel animation:

alt text

For more examples refer to the examples notebooks.

Features

Configuration

The cell magic will default to loading the latest stable version of D3.JS available online (via CDNJS; [email protected] at time of writing). To load a specific version, append the version name to the command, e.g. %%d3 "3.5.17". To load D3.JS from a local file pass the filepath, e.g. %%d3 "d3.v5.min.js".

Only one version of D3.JS may be loaded at a time. Both 3.x and 4.x versions of D3 are supported, but you may only run one version of D3 per notebook. You can check which versions are available by running %d3 versions, and check which version is loaded in the current notebook using %d3 version.

Documentation

Pages from the D3 API Reference may be rendered in-notebook using %d3 doc. For example, you can render the d3-array reference by running %d3 doc "d3-array".

Verbose Mode

You can view code to-be-rendered using verbose mode: %d3 -v. This is helpful for debugging your application.

Technical

How it works

Jupyter notebooks allow executing arbitrary JavaScript code using IPython.display.JavaScript, however it makes no effort to restrict the level of DOM objects accessible to executable code. py_d3 works by restricting d3 scope to whatever cell you are running the code in, by monkey-patching the d3.select and d3.selectAll methods (see here for why this works).

Porting

Most HTML-hosted D3 visualizations, even very complex ones, can be made to run inside of a Jupyter Notebook %%d3 cell with just two modifications:

  • Remove any D3 imports in the cell (e.g. <script src="https://d3js.org/d3.v3.js"></script>).
  • Make sure to create and append to a legal HTML document sub-element. d3.select("body").append("g") won't work.

Contributing

See CONTRIBUTING.md for instructions on how to contribute.

py_d3's People

Contributors

huylenq avatar jobjob avatar mondeja avatar residentmario avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

py_d3's Issues

typo in readme

Wouldn't it be great if we could them to work together?

Maybe this:

Wouldn't it be great if they could work together?

Use requirejs to load d3

d3 version 4.0 no longer exposes the d3 global (d3/d3#2615) when in a requirejs environment (like Jupyter).

Instead of a <script> tag, you'll need to set up the path first:

requirejs.config({
    paths: {
        d3: 'https://d3js.org/d3.v4.js' // Or whatever
    }
})

And then later:

require(['d3'], function(d3) {
 // run d3 logic here. maybe set window.d3 = d3
})

Trap D3 runtime version

The version of D3 that gets loaded you first initialize a notebook with py_d3 code in it is obvious: whatever version of D3 you specify in the first %%d3 call in the notebook, or 3.5.11 if you choose not to pin a version then.

Running multiple version of D3 in the same notebook is unsupported, due to the way require.js handles loading (and this is the correct behavior: this has limited utility anyway, and would cause continuous animations, if you have them, to crash).

However, what happens when you reload a pre-existing notebook is less clear. All of the JavaScript on the page gets executed nearly simultaneously, and, near as I can tell, the first version of the D3 library that gets loaded from the CDN is the one that is pinned.

This means that if you declare e.g. %%d3 4.4.4 in a cell at the beginning of the notebook, then use a clean %%d3 later on, the first time you run the notebook every cell will run 4.4.4 code, but every time after that it'll be a lottery (?), with 3.5.11 a likely winner (which will break any of your v.4 code when you try to run it...).

This inconsistent behavior is a very not-nice usability trap. The workaround right now is to always specify the same specific version in all of your %%d3 calls, so that all of the cells "converge" equivalently.

In the long run, this needs to be patched so that behavior is consistent. I think this can be done by exposing a self.initialized variable in the magic initializer. But it needs testing.

Enable loading D3 locally

Right now using py_d3 requires loading d3 from a CDN, which requires [a half-decent] Internet connection. This isn't totally unreasonable, but as @mdezube pointed out, it'd be great for portability (presentations, working on a flight, etc.) if you could load D3 from a local file instead.

Note that whilst D3 v3 was monolithic, D3 v4 splits its standard lib and optional libraries into multiple separate files. Minify it yourself!

How to wrangle raw selections? Getting a DOMException

Hi there! :)

I've got code that works in a browser on its own, but doesn't transfer to py_d3, and it doesn't seem to fall under the stuff already in the readme or other issues.

Running this code:

%%d3

<style>
.table {
    width: 70%;
}

.table td, th {
    padding: 5px;
}
.table-header {
    background-color: #00AFEF;
    font-weight: bold;
}

.table-row-odd {
    background-color: #f0f8ff;
    color: blue;
}

.table-row-even {
    background-color: #d3d3d3;
}
</style>
<table class="table">
    <thead>
    <tr>
        <th>Time</th>
        <th>Type</th>
        <th>Amount</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>10:22</td>
        <td>Purchase</td>
        <td>$10.00</td>
    </tr>
    <tr>
        <td>12:12</td>
        <td>Purchase</td>
        <td>$12.50</td>
    </tr>
    <tr>
        <td>14:11</td>
        <td>Expense</td>
        <td>$9.70</td>
    </tr>
    </tbody>
</table>

<script type="text/javascript">
    var trSelection = d3.selectAll("tr"); // <-- A

    var headerElement = trSelection.nodes()[0]; // <-- B
    console.log("headerElement is an instance of DOM Element: " 
        + (headerElement instanceof Element));

    d3.select(headerElement).attr("class", "table-header"); // <-- C
    console.log("d3.select(headerElement) is an instanceof of d3.selection: " 
        + (d3.select(headerElement) instanceof d3.selection));

    var rows = trSelection.nodes();
    d3.select(rows[1]).attr("class", "table-row-odd"); // <-- D
    d3.select(rows[2]).attr("class", "table-row-even"); // <-- E
    d3.select(rows[3]).attr("class", "table-row-odd"); // <-- F
</script>

In-browser yields:
screen shot 2018-04-12 at 12 25 42 pm
console:
screen shot 2018-04-12 at 12 25 56 pm

In jupyter/py_d3 yields:
screen shot 2018-04-12 at 12 27 03 pm

Javascript error adding output!
SyntaxError: Failed to execute 'querySelector' on 'Element': '[object HTMLTableRowElement]' is not a valid selector.
See your browser Javascript console for more details.

console:
screen shot 2018-04-12 at 12 28 50 pm

I'm just learning D3 using some tutorials, and I don't know much about DOM manipulation, is there something in jupyter that makes this illegal? I'm going to move on to the next tutorial for now, but wanted to pass this along in case this is a bug rather than a feature. :)

`this` not bound correctly within anonymous event functions in magic cells

TLDR;

Description

this is not bound to the expected element when used inside anonymous event handler functions.

Expected Behavior

this inside anonymous event handler functions to be bound to the element generating the event.

Actual Behavior

this remains bound to the global window.

Verbose

As the title suggests, I'm seeing an issue with the usage of this from within the anonymous function for event listeners for SVG elements when using %%d3 magic cells.

bars.on('mouseover', (data, index) => {
    console.log(this);
    d3.select(this).attr('fill', 'orange');
});

Say I have a d3 selection of elements called bars that represents the rects in a bar graph of an svg. When executing .on(action, anon) I would expect the this within the anonymous function to be bound to the element that triggered the event; however, through some basic console logging I see that this from within the function is bound to the window.

screen shot 2017-06-16 at 4 34 52 pm

The image above shows this being console logged first by the main body of the script, then by the anonymous function.

Fix super() call in D3Magics class

Line 19: The super call is missing arguments:

super(D3Magics, self).__init__(**kwargs)

It didn't run for me until I made that change, and now it works.

Unable to run specific version of D3

I tried to run the py_d3 library on Kaggle kernel, but it failed
Here are the steps I followed

!pip install py_d3
%load_ext py_d3

%%d3
"3.5.17"

However, when I check the version, it points to 5.12.0. This results in the notebook failing to produce any output. I get a d3.scale.category20() undefined error; this is because in the latest version it is d3.schemaCategory20. Interestingly, when I run this locally, on my machine, it runs fine, and the output is rendered. Any idea why it fails on Kaggle?

Any help is appreciated. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.