<h1 align="center">
<img width="230px" src="https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/qgridnext_logo.png">
</h1>
<div align="center">
[Documentation](https://qgridnext.readthedocs.io) | [Demos](https://github.com/zhihanyue/qgridnext-demos) | [Presentation](https://www.youtube.com/watch?v=AsJJpgwIX0Q) | [Changelog](https://qgridnext.readthedocs.io/en/latest/changelog.html)
</div>
<br>
Qgrid is a Jupyter widget that utilizes [SlickGrid](https://github.com/mleibman/SlickGrid) to render pandas DataFrames within JupyterLab/Notebook. This allows you to explore your DataFrames with intuitive scrolling, sorting, and filtering controls, as well as edit your DataFrames by double clicking cells. Initially developed by Quantopian, [Qgrid](https://github.com/quantopian/qgrid) ceased maintenance in 2020. QgridNext aims to continue maintaining and improving it for future Jupyter versions.
![filtering_demo](https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/filtering_demo.gif)
## Compatibility
QgridNext is compatible with recent versions of Jupyter:
| QgridNext | JupyterLab | Notebook | Voila |
|:---------:|:------------:|:--------:|:-----------:|
| v2.0 | v3 - v4 | v5 - v7 | v0.2 - v0.5 |
The test environments are provided in the [test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs) folder. You can try the widget in these environments easily.
## QgridNext V2.0
QgridNext v2.0 significantly improves compatibility and addresses bugs found in Qgrid v1.3.1.
* Support JupyterLab 4;
* Released as a prebuilt extension (now can be installed with one step);
* UI improvements:
* Fix infinitely expanding width of the container in voila <= 0.3;
* Prevent unexpected scrolling when clicking rows in Chrome for JupyterLab;
* Adapt canvas size when the sidebar width changes in JupyterLab;
* Fix poorly displayed left/right button of date picker;
* Correct text color in dark mode;
* Standardize HTML tags to fix poorly displayed filters;
* ...
* Building bug fixes:
* Fix inconsistent pkg name for embeddable qgrid bundle;
* Fix data_files finding that results in incomplete extension setup;
* Fix building errors for Node >= 18;
* Other fixes:
* Ensure `Defaults.grid_option` dict instance are not shared across widget instances;
* Remove full-screen mode for voila compatibility;
* Remove deprecated QGridWidget alias, only QgridWidget is allowed;
* Replace deprecated usages for traitlets, pandas and jquery;
* Support `string[python|pyarrow]`-typed columns;
* ...
* (v2.0.3) Add dark theme support for JupyterLab, Notebook, and VSCode-Jupyter, automatically adapting to the environment's theme.
<p><img width="650px" src="https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/dark_theme.jpg"></p>
## Installation
Installing with pip:
```bash
pip install qgridnext
```
### Requirements
QgridNext supports Python 3.7+ and depends on the following packages:
* [pandas](https://github.com/pandas-dev/pandas) >= 0.20
* [ipywidgets](https://github.com/jupyter-widgets/ipywidgets) >= 7
* [numpy](https://github.com/numpy/numpy)
* [traitlets](https://github.com/ipython/traitlets)
## Usage
### Exploring Dataframes
**Rendering your DataFrame:**
```py
from qgridnext import show_grid
show_grid(your_df)
```
QGrid loads DataFrame lazily, which ensures efficiency for rendering large DataFrames. For example, it can render a DataFrame with 10,000,000 rows in 1 second:
![render_time](https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/render_time.png)
**Column-specific options:** Qgrid has the ability to set a number of options on a per column basis. This allows you to do things like explicitly specify which column should be sortable, editable, etc. For example, to prevent editing on all columns except for a column named 'A', you can do the following:
```py
col_opts = { 'editable': False }
col_defs = { 'A': { 'editable': True } }
show_grid(df, column_options=col_opts, column_definitions=col_defs)
```
**Row-specific options:** Currently, Qgrid supports disabling row editing on a per-row basis, enabling row editability based on specific criteria:
```py
def can_edit_row(row):
return row['status'] == 'active'
show_grid(df, row_edit_callback=can_edit_row)
```
**Updating an existing Qgrid widget**: You can update an existing Qgrid widget's state using APIs like [edit_cell](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.edit_cell), [change_selection](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.change_selection), [toggle_editable](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.toggle_editable), and [change_grid_option](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.change_grid_option).
### Event handlers
Use `on` and `off` methods to attach/detach event handlers. They're available on both the `qgrid` module (see [qgrid.on](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.on)) and individual `QgridWidget` instances (see [qgrid.QgridWidget.on](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.on)).
Example:
```py
def handle_json_updated(event, qgrid_widget):
# Exclude 'viewport_changed' events since that doesn't change the DataFrame
if (event['triggered_by'] != 'viewport_changed'):
print(qgrid_widget.get_changed_df())
# qgrid_widget = show_grid(...)
qgrid_widget.on('json_updated', handle_json_updated)
```
Alternatively, the traditional `observe` method is available but not recommended due to its less granular event control:
```py
def handle_df_change(change):
print(change['new'])
qgrid_widget.observe(handle_df_change, names=['_df'])
```
Event handlers enable interesting integrations with other widgets/visualizations, like using qgrid to filter a DataFrame also displayed by another visualization.
![linked_to_scatter](https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/linked_to_scatter.gif)
For more examples, see the [events notebook](https://github.com/zhihanyue/qgridnext-demos/blob/master/events.ipynb).
## Testing
Multiple test environments are provided in [test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs). You can perform automated tests by pytest, or manually test it in your browser.
## Troubleshoot
If the widget does not appear, first check if the extension is installed and enabled:
```bash
jupyter labextension list
jupyter labextension enable qgridnext # enable it if it's disabled
```
If you encounter an error message like `displaying widget: model not found` or `Loading widget...`, it may indicate a version incompatibility between your ipywidgets and JupyterLab. In most cases, upgrading the ipywidgets version will solve the problem. You can also refer to the environment configurations listed in [test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs).
When upgrading, it's necessary to restart the kernel and refresh the webpage. In some cases, clearing your browser's cache may also be helpful.
Utilizing the test environments ([test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs)) is recommended for efficiently diagnosing any issues within your current setup. If the widget works correctly within the test environment but not in your own, it's likely due to version incompatibilities, which can be resolved by adjusting the versions in your environment accordingly.
## Development
Note: JupyterLab 4 and NodeJS are required to build the extension package. You can use `dev.yml` in [test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs) for a quick setup.
```bash
git clone https://github.com/zhihanyue/qgridnext
cd qgridnext
pip install -ve . # Install package in development mode
```
`pip install -ve .` installs the package into your python environment as a symlink. It also creates symlinks of built JS extensions for your Jupyter environments automatically (implemented by our custom command in `setup.py`). After making any changes to the JS code, just rebuild it by:
```bash
npm --prefix ./js install
```
When uninstalling it, you need to clean up the JS symlinks via script `unlink_dev.py`:
```bash
pip uninstall qgridnext
python ./unlink_dev.py
```
## Contributing
All contributions, bug reports, bug fixes, documentation improvements, enhancements, demo improvements and ideas are welcome.
Raw data
{
"_id": null,
"home_page": "https://github.com/zhihanyue/qgridnext",
"name": "qgridnext",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "ipython, jupyter, widgets",
"author": "QgridNext",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/16/12/4379b367190c06526050d45e96c9747d8cf4fff08fc3b734be8e2c1870c1/qgridnext-2.0.4.tar.gz",
"platform": null,
"description": "<h1 align=\"center\">\n <img width=\"230px\" src=\"https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/qgridnext_logo.png\">\n</h1>\n<div align=\"center\">\n\n[Documentation](https://qgridnext.readthedocs.io) | [Demos](https://github.com/zhihanyue/qgridnext-demos) | [Presentation](https://www.youtube.com/watch?v=AsJJpgwIX0Q) | [Changelog](https://qgridnext.readthedocs.io/en/latest/changelog.html)\n\n</div>\n\n<br>\n\nQgrid is a Jupyter widget that utilizes [SlickGrid](https://github.com/mleibman/SlickGrid) to render pandas DataFrames within JupyterLab/Notebook. This allows you to explore your DataFrames with intuitive scrolling, sorting, and filtering controls, as well as edit your DataFrames by double clicking cells. Initially developed by Quantopian, [Qgrid](https://github.com/quantopian/qgrid) ceased maintenance in 2020. QgridNext aims to continue maintaining and improving it for future Jupyter versions.\n\n![filtering_demo](https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/filtering_demo.gif)\n\n## Compatibility\n\nQgridNext is compatible with recent versions of Jupyter:\n\n| QgridNext | JupyterLab | Notebook | Voila |\n|:---------:|:------------:|:--------:|:-----------:|\n| v2.0 | v3 - v4 | v5 - v7 | v0.2 - v0.5 |\n\nThe test environments are provided in the [test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs) folder. You can try the widget in these environments easily.\n\n\n## QgridNext V2.0\n\nQgridNext v2.0 significantly improves compatibility and addresses bugs found in Qgrid v1.3.1.\n* Support JupyterLab 4;\n* Released as a prebuilt extension (now can be installed with one step);\n* UI improvements:\n * Fix infinitely expanding width of the container in voila <= 0.3;\n * Prevent unexpected scrolling when clicking rows in Chrome for JupyterLab;\n * Adapt canvas size when the sidebar width changes in JupyterLab;\n * Fix poorly displayed left/right button of date picker;\n * Correct text color in dark mode;\n * Standardize HTML tags to fix poorly displayed filters;\n * ...\n* Building bug fixes:\n * Fix inconsistent pkg name for embeddable qgrid bundle;\n * Fix data_files finding that results in incomplete extension setup;\n * Fix building errors for Node >= 18;\n* Other fixes:\n * Ensure `Defaults.grid_option` dict instance are not shared across widget instances;\n * Remove full-screen mode for voila compatibility;\n * Remove deprecated QGridWidget alias, only QgridWidget is allowed;\n * Replace deprecated usages for traitlets, pandas and jquery;\n * Support `string[python|pyarrow]`-typed columns;\n * ...\n* (v2.0.3) Add dark theme support for JupyterLab, Notebook, and VSCode-Jupyter, automatically adapting to the environment's theme.\n <p><img width=\"650px\" src=\"https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/dark_theme.jpg\"></p>\n\n\n\n## Installation\n\nInstalling with pip:\n\n```bash\npip install qgridnext\n```\n\n\n### Requirements\n\nQgridNext supports Python 3.7+ and depends on the following packages:\n\n* [pandas](https://github.com/pandas-dev/pandas) >= 0.20\n* [ipywidgets](https://github.com/jupyter-widgets/ipywidgets) >= 7\n* [numpy](https://github.com/numpy/numpy)\n* [traitlets](https://github.com/ipython/traitlets)\n\n\n## Usage\n\n### Exploring Dataframes\n\n**Rendering your DataFrame:**\n```py\nfrom qgridnext import show_grid\nshow_grid(your_df)\n```\n\nQGrid loads DataFrame lazily, which ensures efficiency for rendering large DataFrames. For example, it can render a DataFrame with 10,000,000 rows in 1 second:\n\n![render_time](https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/render_time.png)\n\n\n**Column-specific options:** Qgrid has the ability to set a number of options on a per column basis. This allows you to do things like explicitly specify which column should be sortable, editable, etc. For example, to prevent editing on all columns except for a column named 'A', you can do the following:\n\n```py\ncol_opts = { 'editable': False }\ncol_defs = { 'A': { 'editable': True } }\nshow_grid(df, column_options=col_opts, column_definitions=col_defs)\n```\n\n**Row-specific options:** Currently, Qgrid supports disabling row editing on a per-row basis, enabling row editability based on specific criteria:\n\n```py\ndef can_edit_row(row):\n return row['status'] == 'active'\nshow_grid(df, row_edit_callback=can_edit_row)\n```\n\n**Updating an existing Qgrid widget**: You can update an existing Qgrid widget's state using APIs like [edit_cell](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.edit_cell), [change_selection](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.change_selection), [toggle_editable](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.toggle_editable), and [change_grid_option](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.change_grid_option).\n\n\n### Event handlers\n\nUse `on` and `off` methods to attach/detach event handlers. They're available on both the `qgrid` module (see [qgrid.on](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.on)) and individual `QgridWidget` instances (see [qgrid.QgridWidget.on](https://qgridnext.readthedocs.io/en/latest/api.html#qgrid.QgridWidget.on)).\n\nExample:\n```py\ndef handle_json_updated(event, qgrid_widget):\n # Exclude 'viewport_changed' events since that doesn't change the DataFrame\n if (event['triggered_by'] != 'viewport_changed'):\n print(qgrid_widget.get_changed_df())\n\n# qgrid_widget = show_grid(...)\nqgrid_widget.on('json_updated', handle_json_updated)\n```\n\nAlternatively, the traditional `observe` method is available but not recommended due to its less granular event control:\n```py\ndef handle_df_change(change):\n print(change['new'])\n\nqgrid_widget.observe(handle_df_change, names=['_df'])\n```\n\nEvent handlers enable interesting integrations with other widgets/visualizations, like using qgrid to filter a DataFrame also displayed by another visualization.\n\n![linked_to_scatter](https://raw.githubusercontent.com/zhihanyue/qgridnext/main/docs/_static/linked_to_scatter.gif)\n\nFor more examples, see the [events notebook](https://github.com/zhihanyue/qgridnext-demos/blob/master/events.ipynb).\n\n## Testing\n\nMultiple test environments are provided in [test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs). You can perform automated tests by pytest, or manually test it in your browser.\n\n## Troubleshoot\n\nIf the widget does not appear, first check if the extension is installed and enabled:\n\n```bash\njupyter labextension list\njupyter labextension enable qgridnext # enable it if it's disabled\n```\n\nIf you encounter an error message like `displaying widget: model not found` or `Loading widget...`, it may indicate a version incompatibility between your ipywidgets and JupyterLab. In most cases, upgrading the ipywidgets version will solve the problem. You can also refer to the environment configurations listed in [test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs).\n\nWhen upgrading, it's necessary to restart the kernel and refresh the webpage. In some cases, clearing your browser's cache may also be helpful.\n\nUtilizing the test environments ([test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs)) is recommended for efficiently diagnosing any issues within your current setup. If the widget works correctly within the test environment but not in your own, it's likely due to version incompatibilities, which can be resolved by adjusting the versions in your environment accordingly.\n\n## Development\n\nNote: JupyterLab 4 and NodeJS are required to build the extension package. You can use `dev.yml` in [test_envs](https://github.com/zhihanyue/qgridnext/tree/main/test_envs) for a quick setup.\n\n```bash\ngit clone https://github.com/zhihanyue/qgridnext\ncd qgridnext\npip install -ve . # Install package in development mode\n```\n\n`pip install -ve .` installs the package into your python environment as a symlink. It also creates symlinks of built JS extensions for your Jupyter environments automatically (implemented by our custom command in `setup.py`). After making any changes to the JS code, just rebuild it by:\n\n```bash\nnpm --prefix ./js install\n```\n\nWhen uninstalling it, you need to clean up the JS symlinks via script `unlink_dev.py`:\n\n```bash\npip uninstall qgridnext\npython ./unlink_dev.py\n```\n\n\n## Contributing\n\nAll contributions, bug reports, bug fixes, documentation improvements, enhancements, demo improvements and ideas are welcome.\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "An Interactive Grid for Sorting and Filtering DataFrames in Jupyter",
"version": "2.0.4",
"project_urls": {
"Homepage": "https://github.com/zhihanyue/qgridnext"
},
"split_keywords": [
"ipython",
" jupyter",
" widgets"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "bd9c133709f00aea48328bd1efc66a1c961a61a66aab344e07077aace2ad113b",
"md5": "daf8e1f2b11e21adc7a5475d1f5082f6",
"sha256": "83692cd8f3b8515f2d0f3488b9e9944c180398ab4bae75fc6c83402ba3a9b9fb"
},
"downloads": -1,
"filename": "qgridnext-2.0.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "daf8e1f2b11e21adc7a5475d1f5082f6",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 1263587,
"upload_time": "2024-11-03T18:20:58",
"upload_time_iso_8601": "2024-11-03T18:20:58.173709Z",
"url": "https://files.pythonhosted.org/packages/bd/9c/133709f00aea48328bd1efc66a1c961a61a66aab344e07077aace2ad113b/qgridnext-2.0.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "16124379b367190c06526050d45e96c9747d8cf4fff08fc3b734be8e2c1870c1",
"md5": "783cacd0bf065dc91f73a24d3b11a4d0",
"sha256": "5312d688f133fb9622ccf819f5bef99d6df86a343122cc193c35801a732a5ccc"
},
"downloads": -1,
"filename": "qgridnext-2.0.4.tar.gz",
"has_sig": false,
"md5_digest": "783cacd0bf065dc91f73a24d3b11a4d0",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 1263843,
"upload_time": "2024-11-03T18:21:00",
"upload_time_iso_8601": "2024-11-03T18:21:00.879065Z",
"url": "https://files.pythonhosted.org/packages/16/12/4379b367190c06526050d45e96c9747d8cf4fff08fc3b734be8e2c1870c1/qgridnext-2.0.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-03 18:21:00",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "zhihanyue",
"github_project": "qgridnext",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "qgridnext"
}