Code Monkey home page Code Monkey logo

d3py's Introduction

Hello

August 2013

Hello! Maybe you're looking for a nice Python interface to build interactive, javascript based plots that look as nice as all those d3 plots you've been seeing lately? Well, this repository is not a bad place to start looking. The code herein was an experiment to see if this approach was a good idea and, if it was, what the experience of plotting into the browser from Python would feel like.

All the code should work, more or less, and you are welcome to fork it, muck about with it, and generally get a taste for what this sort of plotting feels like.

You probably don't want to stop reading here, though. Instead, you should go check out vincent which is a much nicer take on this idea, created using vega, and is in general a much more gentlemanly way to go about this sort of thing. It's also being properly updated and developed, unlike the code below.

d3py

This is d3py: a plotting library for python based on d3. The aim of d3py is to provide a simple way to plot data from the command line or simple scripts into a browser window.

d3py accomplishes this by building on two excellent packages. The first is d3.js (Mike Bostock), which is a javascript library for creating data driven documents, which allows us to place arbitrary svg into a browser window. The second is the pandas Python module (Wes Mckinney), which blesses Python with (amongst other things) the DataFrame data structure.

The idioms used to plot data are very simple, and borrow from R's ggplot2 (Hadley Wickham) and Python's matplotlib (John Hunter et al).

Install d3py and dependencies:

  1. easy_install https://github.com/mikedewar/d3py/tarball/master
  2. pip install pandas
  3. pip install numpy
  4. pip install networkx

Example:

  1. create a PandasFigure object around a DataFrame (or a NetworkXFigure object around a Graph)
  2. add geoms to the figure object to plot specific combinations of columns of the data frame.
  3. show the figure, which serves up the figure in a browser window
  4. muck about with the style of the plot using the browser's developer tools
  5. share FTW!

Each geom takes as parameters an appropriate number of column names of the data frame as arguments. For example the Line geom, which has two dimensions, takes an x-value and a y-value. A Point geom, which makes up a scatter plot, has three dimensions and so takes three parameters: x, y and colour (in the future it could take size, too!).

Each geom is styled using css which you can pass in arbitrarily. So, for example, the Point geom comes with a bunch of default styles, but you can also specify fill=red as a keyword argument which will add a custom css line for that set of points which will turn them red. This also means you can style the plot live in the browser using Firebug in Firefox or Chrome's developer tools.

d3py aims to create really simple javascript source code wherever possible, so you can go in and edit the plots to embed them into your own sites if needs be. The .show() method writes an html file containing the basic markup, a css file with the styles for each geom, a json file with the data from the Figure's DataFrame and a js file with the d3 code in it. The strings that generate the js and css files can always be pulled from the Figure object so you can see how d3py builds up your graph.

An example session could like:

import d3py
import pandas
import numpy as np
	
# some test data
T = 100
# this is a data frame with three columns (we only use 2)
df = pandas.DataFrame({
    "time" : range(T),
    "pressure": np.random.rand(T),
    "temp" : np.random.rand(T)
})
## build up a figure, ggplot2 style
# instantiate the figure object
fig = d3py.PandasFigure(df, name="basic_example", width=300, height=300) 
# add some red points
fig += d3py.geoms.Point(x="pressure", y="temp", fill="red")
# writes 3 files, starts up a server, then draws some beautiful points in Chrome
fig.show() 

Check out the examples in the folder for more functionality! Assuming everything is working OK, the examples should generate (something akin to) the following plots:

point

point example

line

line example

bar

bar example

area

area example

d3py's People

Contributors

adrian-em avatar andrewcstewart avatar ewheeler avatar mikedewar avatar mjhea0 avatar mynameisfiber avatar widdowquinn avatar wrobstory 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  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

d3py's Issues

deal with missing data

In Pandas missing data seems to be represented as numpy.NaN. We need to make sure that no element is bound to an NaN by accident!

remove all formatting from code generation

Hey! We can remove any code formatting (like all those ugly tabs) from the code generation and just run some jslint on the generated code to make it human pretty. Has the added benefit of testing the outgoing code for errors...

readme sample doesn't render with geoms.Bar

The sample code in the readme works as it is, but if I change line 17 to:

fig += d3py.geoms.Bar(x="time", y="temp",fill="red")

It fails to render in firefox or chrome. However, all of the requests (js, json, html) return 200 except for the favicon.ico.

_clanup() - what is it purpose?

Hello,

There is a method stub called _clanup() in the Figure class which simply raises NotImplementedError. What is the purpose of it?

-jk

Problem with new examples

python d3py_bar.py
Cleanup after exception: <type 'exceptions.AttributeError'>: 'module' object has no attribute 'xAxis'
Cleaning temp files
Traceback (most recent call last):
File "d3py_bar.py", line 12, in
p += d3py.xAxis(x = "apple_type")
AttributeError: 'module' object has no attribute 'xAxis'
Cleaning temp files
Exception AttributeError: "'Bar' object has no attribute 'cleanup'" in <bound method Bar.del of <d3py.geoms.Bar object at 0x272f650>> ignored

Tooltips on Plots

great library. putting in tooltips for scatterplots would be awesome

Stream files to webserver instead of saving to disk

As the title says... this should help with ipython compatibility and would vastly simplify cleanup. This could be done with simple modifications to the figure object and a new HTTPServer object (HTTPFileStreamServer?).

host agnostic

It'd be nice to let this work on non-localhosts (like ec2 instances). Right now d3py/d3py_template.html has localhost hard coded, ie:

<script type="text/javascript" charset="utf-8" src="localhost:{{ port }}/static/d3.js"></script>',</code>

It would be nice if this was templated to

<script type="text/javascript" charset="utf-8" src="{{ host }}:{{ port }}/static/d3.js"></script>',

...And anywhere else that change would have to be made.

Have multiple javascript functions in client

We should have multiple functions available to add to from the geometries in the figure object. Two that are required are an init function and a draw function. New functions should handled as well.

In my opinion, this should be done with a dictionary of javascript functions which are merged under addition before rendering. Merging javascript function objects appends them to another so we should be fine.

Also, is there a way to define a scope within a javascript block (similar to wrapping code in {}'s in C code)? This would help with variable munging when we concatenate functions.

Handle Arbitrary Numer of Data Files

The main figure should be able to handle an arbitrary number of data files. This will be very important when implementing maps since we also need to provide the map paths to the client.

del statement fails to clean up files

(Problem exposed while dealing with pull #25)

del is not what we want to cleanup files: the reference count could be at zero even if we have stale files lying around!

One solution would be to use enter and exit and require the user to create a figure object with the with statement:

with Figure() as fig:
...do stuff with fig...

ideas?

Setup.py upgrade

We need to install the static files somewhere where we can later retrieve them (/usr/share/python-d3py?)

accept datetime objects

d3 has great support for javascript's Date objects. We should be able to pass in datetime objects and have them converted...

Venn diagram

It would be cool to draw a ven diagram from python sets

autocall=True

autocall = True doesn't seem to do whatever it's supposed to do!

have bar default to using the Pandas index as its x-domain

suggested idiom:

df = pandas.DataFrame(
    {
        "count" : [1,4,7,3,2,9],
    },
    index = ["a", "b", "c", "d", "e", "f"]
)

with d3py.Figure(df) as p:
    p += d3py.Bar(y = "count")
    p += d3py.xAxis()
    p.show()

this would draw the bar chart with the index as the x-bins.

start tornado server if it's not already running

At the moment, you need to manually run python server.py before doing any plotting. There's no real reason that the user should have to do this - we should start a server when the user first plots something and keep it going until some appropriate time. I don't know what that time should be...

Wiki is out of date!

Well.... the title explains it. I would update it, but you know... I have some nebulous "other stuff" to do.

add a method to Figure that takes in new data

The new method should look like

data = DataFrame({'y' = [1,2,3], 'x' = [1,2,3]})
p = Figure(data)
p += Line(x='x', y='y')
p += DataFrame({'z' = [3,4,5], 'x' = [2,3,4]})
p += Line(x='x', y='z')

and the internal data frame should have merged the xs and added missing data for the ys and zs that don't have data points.

re-factor to make it easy to deploy and support other web technologies.

Hello Mike,

I was looking at the d3py python module. At the moment, it is tightly coupled with python’s SimpleHTTPServer. From a desktop, this works well interactively.

Have you considered a Model/View split? This would provide a good way to deploy d3. Figure and its subclasses would make fine models, but all code which is specific to a web server would be refactored into a class which knows about the Simple HTTP Server. Another class would know how to write to the file system. It might look something like:

// encapsulates all code related to the SimpleHTTPServer implementation.
vHttp = createHTTP(“www.example.com”, 8080)
// creates a class which knows one to write the d3 code to the filesystem for deployment.
vFs = createFS(“~/workspace/opportunity/static”)

// This call is just a placeholder. It will take fewer args as web specific args
// would be passed to creatHTTP().
fig = PandasFigure(...)

// The user can show it. The functionality will be the as it is now.
vHttp.show(fig)
// and/or they can save it to a file system which could be handed off to deploy on the website.
vFs.save(fig)

The added benefit of this pattern is it can extended. This may be particularly useful for HTTP as there are a plethora of web servers and web technologies. New classes could be created for integration and/or deployment.

What do you think?

Regards,
John

handle interrupt more smoothly when using 'with' idiom

When I ctrl-c out of a show when using 'with' python pukes a big long error, even though we direct the user to ctrl-c out of the blocking loop. Let's at least make the error not happen (and let's think about re-writing this at some point eh?).

multiple plots

There should be the facility to plot multiple line graphs and stacked bar charts

log scale axes

The user should be able to specify that the x, y or both axes should be log-scale

How to plot multiple lines

Hello,
thanks for this great module!
I would like to know the proper technique to plot multiple line on a PandasFigure?
What id the proper Data Frame and how to call it?
for example:
i would like to plot two lines on the same figure defined by x,y.
How can i tel d3py to use a dataframe like that:
x y
0 [1, 2] [10, 11]
1 [3, 4] [13, 14]
thanks

javascript cast method

right now

JavaScript() + draw

casts draw to a Javascript object, which isn't terribly clear.

Server shuts down directly after fig.show()

python test.py
you can find your chart at http://localhost:8000/basic_example/basic_example.html
Shutting down httpd
Cleaning temp files

The browser window opens but the server is already shut down.

Source code:

import d3py
import pandas
import numpy as np
# some test data
T = 100
# this is a data frame with three columns (we only use 2)
df = pandas.DataFrame({
    "time" : range(T),
    "pressure": np.random.rand(T),
    "temp" : np.random.rand(T)
})
## build up a figure, ggplot2 style
# instantiate the figure object
fig = d3py.Figure(df, name="basic_example", width=300, height=300) 
# add some red points
fig += d3py.geoms.Point(x="pressure", y="temp", fill="red")
# writes 3 files, starts up a server, then draws some beautiful points in Chrome
fig.show()

IOError: [Errno 2] No such file or directory: 'static/d3.js'

I tried to run the sample program from README:

import d3py
import pandas
import numpy as np

# some test data
T = 100
# this is a data frame with three columns (we only use 2)
df = pandas.DataFrame({
    "time" : range(T),
    "pressure": np.random.rand(T),
    "temp" : np.random.rand(T)
})
## build up a figure, ggplot2 style
# instantiate the figure object
fig = d3py.Figure(df, name="basic_example", width=300, height=300) 
# add some red points
fig += d3py.geoms.Point(x="pressure", y="temp", fill="red")
# writes 3 files, starts up a server, then draws some beautiful points in Chrome
fig.show() 

Error:

Traceback (most recent call last):
  File "sample.py", line 15, in <module>
    fig = d3py.Figure(df, name="basic_example", width=300, height=300) 
  File "/Users/amjith/.virtualenvs/d3py/lib/python2.7/site-packages/d3py/d3py.py", line 97, in __init__
    self.filemap = {"static/d3.js":{"fd":open("static/d3.js","r"), "timestamp":time.time()},}
IOError: [Errno 2] No such file or directory: 'static/d3.js'
Error in clean-up: 'Figure' object has no attribute 'httpd'

Here's my pip freeze

d3py==0.1.0
numpy==1.6.2
pandas==0.10.0
python-dateutil==2.1
pytz==2012h
six==1.2.0
wsgiref==0.1.2

support for python 3

At the moment, d3py needs some modifications to work on Python 3. I think all the supporting modules are available on py 3. How about d3py?

axis labels

take axis labels from the data frame column names unless explicity overruled

Can't run d3py_graph.py example: 'NetworkXFigure' object has no attribute 'httpd'

I cloned d3py and tried to run the d3py_graph.py example, but ran into a problem.

$ git clone git://github.com/mikedewar/d3py.git
[...]
$ cd d3py/
$ python setup.py install
[...]
$ cd examples/
$ python d3py_graph.py 
Traceback (most recent call last):
  File "d3py_graph.py", line 15, in <module>
    with d3py.NetworkXFigure(G, width=500, height=500) as p:
  File "[...]/local/lib/python2.7/site-packages/d3py/networkx_figure.py", line 39, in __init__
    port=port, **kwargs
TypeError: __init__() takes exactly 10 arguments (9 given)
Error in clean-up: 'NetworkXFigure' object has no attribute 'httpd'

I just discovered d3py a few minutes ago, so forgive me if I've missed something. I got the demo to run like this:

$ git diff
diff --git a/examples/d3py_graph.py b/examples/d3py_graph.py
index 99c73ba..b1d9e6a 100644
--- a/examples/d3py_graph.py
+++ b/examples/d3py_graph.py
@@ -12,6 +12,6 @@ G.add_edge(3,4)
 G.add_edge(4,2)

 # use 'with' if you are writing a script and want to serve this up forever
-with d3py.NetworkXFigure(G, width=500, height=500) as p:
+with d3py.NetworkXFigure(G, width=500, height=500, host='localhost') as p:
     p += d3py.ForceLayout()
     p.show()

Unlike PandasFigure(Figure), NetworkXFigure(Figure) does not have a default host argument.

No module named axis

Traceback (most recent call last):
File "testd3.py", line 1, in
import d3py
File "/usr/local/lib/python2.7/dist-packages/d3py/init.py", line 2, in
from geoms import *
File "/usr/local/lib/python2.7/dist-packages/d3py/geoms/init.py", line 5, in
from axis import Axis
ImportError: No module named axis

when running the example code

import d3py
import pandas
import numpy as np

some test data

T = 100

this is a data frame with three columns (we only use 2)

df = pandas.DataFrame({
"time" : range(T),
"pressure": np.random.rand(T),
"temp" : np.random.rand(T)
})

build up a figure, ggplot2 style

instantiate the figure object

fig = d3py.Figure(df, name="basic_example", width=300, height=300)

add some red points

fig += d3py.geoms.Point(x="pressure", y="temp", fill="red")

writes 3 files, starts up a server, then draws some beautiful points in Chrome

fig.show()

dbus error

System: Fedora 16
Installed from git repo

When i run any of the examples, i get:

$ python d3py_scatter.py
you can find your chart at http://localhost:8000/my_figure/my_figure.html

(gnome-open:12202): GConf-WARNING **: Client failed to connect to the D-BUS daemon:
Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
GConf Error: No D-BUS daemon running

Shutting down httpd

DBUS is installed and running.

Thanks!

print html snippet from d3py

scenario:
In python web applications, one would want to insert d3 visualization with d3py by "printing" html snippet to an existing html. For example, googleVis package in R provides such functionality in its print function, which can be used with R markdown to produce html page easily.

AttributeError: 'module' object has no attribute 'Figure'

I get the following error when running the example code in the README:

File "d3py.py", line 1, in <module>
    import d3py
  File "/Users/sloria1/projects/sandbox/d3py.py", line 15, in <module>
    fig = d3py.Figure(df, name="basic_example", width=300, height=300) 
AttributeError: 'module' object has no attribute 'Figure'

From the README:

import d3py
import pandas
import numpy as np

# some test data
T = 100
# this is a data frame with three columns (we only use 2)
df = pandas.DataFrame({
    "time" : range(T),
    "pressure": np.random.rand(T),
    "temp" : np.random.rand(T)
})
## build up a figure, ggplot2 style
# instantiate the figure object
fig = d3py.Figure(df, name="basic_example", width=300, height=300) 
# add some red points
fig += d3py.geoms.Point(x="pressure", y="temp", fill="red")
# writes 3 files, starts up a server, then draws some beautiful points in Chrome
fig.show()

Color aesthetic mapping

The user should be able to map a variable to the color of each shape on the graph. In ggplot, this would run:

require(ggplot2)
df = data.frame(x=rnorm(100), y=rnorm(100, 10, 1), color=rep(1:4, 25))
ggplot(data = df)+geom_point(aes(x = x, y= y, color=color))

It seems like a simple enough fix for geom_point at least. Is there a reason why this hasn't been done?

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.