Giter VIP home page Giter VIP logo

vizzuhq / ipyvizzu Goto Github PK

View Code? Open in Web Editor NEW
923.0 16.0 88.0 21.33 MB

Build animated charts in Jupyter Notebook and similar environments with a simple Python syntax.

Home Page: https://ipyvizzu.vizzuhq.com

License: Apache License 2.0

Python 42.84% JavaScript 2.97% HTML 0.71% Jupyter Notebook 53.49%
jupyter jupyter-notebook python plotting graphs data-visualization graphing ipython chart charts

ipyvizzu's People

Contributors

csaladenes avatar csetedaniel avatar dannylee8 avatar dataombudsman avatar goodwanghan avatar katehyerinjeon avatar kleink0910 avatar m1lk4 avatar maria99898 avatar nandordevai avatar nyirog avatar parkerkain avatar petervidos avatar pplonski avatar shivraj-nakum avatar shruagarwal avatar simzer avatar sugatoray avatar veghdev 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

ipyvizzu's Issues

mode.com support

Mode.com notebook won't show output div for the display_javascript call.
The vizzu div should be created manually using display_html when show() called.

configurable auto store/restore

Would be good to optionally have the possibility to automatically store the chart at the end of the cell and restore at the beginning of the cell, like in the tutorial, configurable by a parameter.

Validate Data

it would be better to validate the json data

from jsonschema import validate

NAMED_VALUES_SCHEMA = {
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "name": {
                "type": "string"
            },
            "values": {
                "type": "array"
            }
        },
        "required": ["name", "values"]
    } 
}

SCHEMA = {
    "type": "object",
    "properties": {
        "records": {
            "type": "array",
        },
        "series": NAMED_VALUES_SCHEMA,
        "measures": NAMED_VALUES_SCHEMA,
        "dimensions": NAMED_VALUES_SCHEMA,
    }
}

class Data(Animation):
    @classmethod
    def from_json(cls, filename):
        with open(filename) as file_desc:
            data = json.load(file_desc)

       validate(data, SCHEMA)
       return cls(data)

The validation does not have to be jsonschema. We could use typing.NamedTuple, dataclasses or attrs, but they unfortunately don't have from_dict method .

Originally posted by @nyirog in #37 (comment)

Basic support for vizzu events

https://lib.vizzuhq.com/latest/#chapter-0.16

proposal: js functions passed as string

clickHandler = chart.on("click", "alert(JSON.stringify(event.data));");
chart.off('click', clickHandler);

generate JS code:

let eventHandler1231245 = event => { alert(JSON.stringify(event.data)); };
chart.on("click", eventHandler1231245);
chart.off('click', eventHandler1231245);

Restrict Vizzu's versions

Wouldn't be better to have some preset value for vizzu source instead of a free style str?

import enum

class VizzuSource(str, enum.Enum):
    latest = "https://cdn.jsdelivr.net/npm/vizzu@latest/dist/vizzu.min.js"
    ...

class Chart:
    def set_vizzu(self, source: VizzuSource):
        self._vizzu_url = source

Originally posted by @nyirog in #40 (comment)

Does not work in Deepnote

https://deepnote.com

The problem seems to be, that this environment creates separate HTML documents for each cell including them into the notebook using iframe, also creates separate js files for all script tag inside a cell.

doc: empty jp-OutputPrompt jp-OutputArea-prompt fields not well format

When ipyvizzu relocates (animate) vizzu's div, empty jp-OutputPrompt jp-OutputArea-prompt fields are created.

These fields are invisible in the jupyter notebook, but they are visible and not well formatted in the html doc.
The style params of these fields depends on the html template (default lab), so a hot fix can be the create the doc with a custom ipyvizzu template.

But if someone will use ipyvizzu in a project, and use nbconvert to generate htmls from the notebooks, the problem still be there.
I think the adequate solutions can be if ipyvizzu remove this empty fields if it is possible.

js_separation branch: chart does not move in generated htmls

With the new separated js class in the generated htmls the chart displayed after the first cell, and not moved (display="actual")
Even with manually saved ipynb output, even if nbconvert generated it.

Example:

cd tools/html-generator

with execute flag *if output not created and saved manually:
../../.venv/bin/jupyter nbconvert --Exporter.preprocessors=preprocessor.NbPreprocessor --to html --execute ../../docs/tutorial/sorting.ipynb

without execute flag *if output created and saved manually:
../../.venv/bin/jupyter nbconvert --Exporter.preprocessors=preprocessor.NbPreprocessor --to html ../../docs/tutorial/sorting.ipynb

No scroll in case of user scroll

If the notebook is running and the user scrolls, then auto scrolling should switch off for that run.
It is inconvenient for the user that they couldn't scroll during running.

Something like this would be the solution:

global scope:

let inhibitScroll = false;
document.addEventListener('scroll', function(e) {
  inhibitScroll = true;
});

cell:

if (!inhibitScroll) myVizzu.scrollIntoView(...);

I don't how to set inhibitScroll back to false after running, but next run should do autoscrolling again.

Support Vizzu data filter

Data filter can be specified for Vizzu on the JS API as a JS function:

chart.animate({ data: { filter: record => expression ) }});

where data series can be referenced through the record object, e.g.:

record => { return record["foo"] == "blabla" || record["baz"] > 5; } 

It would be good to have two possibilities to define this filter on the ipyvizzu API

  • Simple solution, supplying the JS expression in a string:

    Python:

    filter = JSExpression("string-of-JS-code")

    where ipyvizzu should generate the following JS code:
    JS:

    filter: record => { return (string-of-JS-code); }

    e.g.:

    Python:

    filter = JSExpression("record['foo'] == 'blabla' || record['baz'] > 5")

    =>
    JS:

    filter: record => { return record['foo'] == 'blabla' || record['baz'] > 5; }
  • Through Python wrapper object with overloaded operators building the js code under the hood.
    Python:

    filter = Series("foo") == "blabla" || Series("baz" > 5)

    where ipyvizzu should generate the following:
    JS:

    filter: record => { return record["foo"] == "blabla" || record["baz"] > 5; }

    Operators, which should be supported:
    ==, !=, <, <=, >=, >, ||, &&

change doc online version

I have a question about the online version of the documentation.

If I change something in a ipynb file in doc/examples, after that I need to run make doc and commit changed htmls if I want to update the site too? (In that case I do not understand clearly what pages-build-deployment workflow do.)

Refactor ipyvizzu.Chart.animate() to handle animoptions

ipyvizzu.Chart.animate() can not handle animoptions (like delay, duration etc.).

The JS API accepts the following arguments:
animate({ data, config, style }, animoptions)
animate(config, animoptions)
animate({ data, config, style })
animate(config)

ipyvizzu's behavior do not need to be the same like the JS API, so it can be pythonic, but the functions have to work.
(animoptions is a js object like a python dict, or in js api it can be a single string if only want to change the duration so '500ms' instead of {duration: '500ms'})

I think possible solutions in ipyvizzu are:

I.
kwargs only be animoptions
style, data and config only be Style, Data, Config classes in args
(it is a further problem with this, Style(None) needs to work to reset previous style modifications, but now it is working only in kwargs style=None)

II.
create az animOptions class, and handle it differently in _merge_animations()

III.
any other idea

environment issues: use ipyvizzu with Panel

Panel is a powerful framework for #dataapps in #python. It would be really nice if it was easy to use Ipyvizzu with Panel.

As a first step I created an example of how this can be done. See https://discourse.holoviz.org/t/animated-charts-and-story-telling-with-ipyvizzu/3622 for the details.

works-with-ipyvizzu

I've made a small tweet about it here https://twitter.com/MarcSkovMadsen/status/1518219138266804224?s=20&t=qKrkT52SeEvRLp74fHpE6g. I've shared it on LinkedIn here https://www.linkedin.com/posts/marcskovmadsen_dataapp-python-dataapp-activity-6923988516120985600-qJ_C?utm_source=linkedin_share&utm_medium=member_desktop_web.

To make it easy would probably either include some documentation on the ipyvizzu side and/ or a custom Panel pane that users can wrap the Ipyvizzu chart in to get it rendered.

This issue is mostly for info at the current state such that your community knows it can be done.

doc: import data

Import data classes of the examples instead of copy then into every snippet.

add_data_frame does not work with None and pd.Series

Tested. Works in certain cases.
Seems to be working ok on:

  • pd.DataFrames of various shapes, including 1 x n and n x 1
  • empty DataFrame
  • index and column names of any type, including str and int
  • when passed DataFrame contains None or np.nan elements

Does not work when:

  • passing a pd.Series as an argument
    • Temporary workaround: use [[ ]] on your data and pass it as a n x 1 DataFrame instead
  • passing only a None as argument
    • Temporary workaround: use an empty DataFrame object instead

Originally posted by @csaladenes in #69 (review)

Quick fix: Insert in line 1 of add_df:

if type(df) in [type(None)]: return {} # return empty dict if NoneType
  else:
    if type(df)==pd.core.series.Series:
      df=pd.DataFrame(df) # force type to DataFrame
      for name ...

Makes it dependent on pandas imported as pd of course.

Originally posted by @csaladenes in #69 (comment)

Generate ipynb from python and markdown assets

The notebooks (ipynb) inculdes the markdown and code cells as list of lines. Editing the notebook is error prone therefore we should read the cells from separate assets.

A notebook

{                                                                                                                                                                                                                      
  "cells": [                                                                                 
    {                                                                                         
       "cell_type": "markdown",                                                              
       "id": "e582c95b",                                                                     
       "metadata": {},                                                                       
       "source": [                                                                           
          "## Aggregate/drill-down\n",                                                         
          "\n",                                                                                
          "These features basically mean that you add or remove an additional dimension to/from an axis or another channel. As you can see below, there are some important things to keep in mind when you use them.\n",
          "\n",                                                                                
          "Let’s stack together the elements by putting the Genres dimension from the x-axis to the y-axis. At the end of this phase, there are chart elements with the same color stacked on top of each other, which is something you would want to avoid. "
      ]                                                                                     
    }
  ]
}

would be split into a json and markdown/python files

{                                                                                                                                                                                                                      
  "cells": [                                                                                 
    {                                                                                         
      "cell_type": "markdown",                                                              
      "id": "e582c95b",                                                                     
      "metadata": {},                                                                       
      "source": {"@readlines": "aggregate.md"}
    }
  ]                                                                                     
}
## Aggregate/drill-down

These features basically mean that you add or remove an additional dimension to/from an axis or another channel. As you can see below, there are some important things to keep in mind when you use them.

Let’s stack together the elements by putting the Genres dimension from the x-axis to the y-axis. At the end of this phase, there are chart elements with the same color stacked on top of each other, which is something you would want to avoid.

The {"@readlines": "aggregate.md"} would be handle by a simple python script with the json.load object_hook. And the Makefile would genearte ipynb from the json template:

#!/usr/bin/env python3
"""
Replace `{"@readlines": "referred/file"}` object from the `json_file` with the
list of lines read from the referred file. The path of the referred file is
relative to the `json_file`.
"""

import argparse
import json
import sys
import pathlib


def main():
    args = _parse_args()
    reader = Reader(args.json_file.parent)

    with args.json_file.open() as fp:
        obj = json.load(fp, object_hook=reader.object_hook)

    json.dump(obj, fp=sys.stdout, indent=4, sort_keys=True)


def _parse_args():
    parser = argparse.ArgumentParser(
        description="Read files as list of lines into json", epilog=__doc__
    )
    parser.add_argument("json_file", type=pathlib.Path)

    return parser.parse_args()


class Reader:
    def __init__(self, source_dir):
        self._source_dir = source_dir

    def object_hook(self, obj):
        if len(obj) != 1:
            return obj

        try:
            path = obj["@readlines"]
        except KeyError:
            return obj

        file_name = self._source_dir / path

        with file_name.open() as fp:
            return fp.readlines()


if __name__ == "__main__":
    exit(main())

How to loop the animation? Add controls?

This is a great library! Exactly the lib that I was looking for! Thank you! 🥇

How to run the animation in the loop? Can I add controls for animation (stop, play)?

I'm working on a framework for converting Jupyter Notebooks to interactive web apps. Would love to use vizzu in demos. I will let you know, thanks!

bug: chart duplicated

If run initiated on a cell while another cell did not finished running, then the chart div somehow gets duplicated.

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.