├── tabel.egg-info ├── top_level.txt ├── dependency_links.txt ├── requires.txt ├── SOURCES.txt └── PKG-INFO ├── tabel ├── _version.py ├── git_version.py ├── numpy_types.py ├── __init__.py ├── util.py └── hashjoin.py ├── .flake8 ├── docs ├── source │ ├── license.rst │ ├── api │ │ ├── index.rst │ │ ├── module.rst │ │ └── tabel.rst │ ├── readme.rst │ ├── index.rst │ ├── conf.py │ └── performance.rst ├── test.npz ├── build │ ├── html │ │ ├── _sources │ │ │ ├── license.rst.txt │ │ │ ├── api │ │ │ │ ├── index.rst.txt │ │ │ │ ├── module.rst.txt │ │ │ │ └── tabel.rst.txt │ │ │ ├── readme.rst.txt │ │ │ ├── index.rst.txt │ │ │ └── performance.rst.txt │ │ ├── objects.inv │ │ ├── _static │ │ │ ├── up.png │ │ │ ├── down.png │ │ │ ├── file.png │ │ │ ├── minus.png │ │ │ ├── plus.png │ │ │ ├── comment.png │ │ │ ├── up-pressed.png │ │ │ ├── ajax-loader.gif │ │ │ ├── down-pressed.png │ │ │ ├── comment-bright.png │ │ │ ├── comment-close.png │ │ │ ├── fonts │ │ │ │ ├── Lato │ │ │ │ │ ├── lato-bold.eot │ │ │ │ │ ├── lato-bold.ttf │ │ │ │ │ ├── lato-bold.woff │ │ │ │ │ ├── lato-bold.woff2 │ │ │ │ │ ├── lato-italic.eot │ │ │ │ │ ├── lato-italic.ttf │ │ │ │ │ ├── lato-italic.woff │ │ │ │ │ ├── lato-italic.woff2 │ │ │ │ │ ├── lato-regular.eot │ │ │ │ │ ├── lato-regular.ttf │ │ │ │ │ ├── lato-regular.woff │ │ │ │ │ ├── lato-regular.woff2 │ │ │ │ │ ├── lato-bolditalic.eot │ │ │ │ │ ├── lato-bolditalic.ttf │ │ │ │ │ ├── lato-bolditalic.woff │ │ │ │ │ └── lato-bolditalic.woff2 │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ ├── fontawesome-webfont.woff2 │ │ │ │ └── RobotoSlab │ │ │ │ │ ├── roboto-slab-v7-bold.eot │ │ │ │ │ ├── roboto-slab-v7-bold.ttf │ │ │ │ │ ├── roboto-slab-v7-bold.woff │ │ │ │ │ ├── roboto-slab-v7-bold.woff2 │ │ │ │ │ ├── roboto-slab-v7-regular.eot │ │ │ │ │ ├── roboto-slab-v7-regular.ttf │ │ │ │ │ ├── roboto-slab-v7-regular.woff │ │ │ │ │ └── roboto-slab-v7-regular.woff2 │ │ │ ├── documentation_options.js │ │ │ ├── css │ │ │ │ └── badge_only.css │ │ │ ├── js │ │ │ │ └── theme.js │ │ │ ├── pygments.css │ │ │ ├── doctools.js │ │ │ ├── underscore.js │ │ │ └── basic.css │ │ ├── .buildinfo │ │ ├── search.html │ │ ├── py-modindex.html │ │ ├── license.html │ │ ├── searchindex.js │ │ ├── api │ │ │ ├── index.html │ │ │ └── module.html │ │ └── genindex.html │ ├── doctrees │ │ ├── index.doctree │ │ ├── license.doctree │ │ ├── readme.doctree │ │ ├── api │ │ │ ├── index.doctree │ │ │ ├── module.doctree │ │ │ └── tabel.doctree │ │ ├── cookbook.doctree │ │ ├── environment.pickle │ │ └── performance.doctree │ └── doctest │ │ └── output.txt ├── test.csv └── Makefile ├── test ├── test.npz ├── .pytest_cache │ ├── v │ │ └── cache │ │ │ ├── lastfailed │ │ │ └── nodeids │ └── README.md ├── .cache │ └── v │ │ └── cache │ │ └── lastfailed └── test_tabel.py ├── MANIFEST.in ├── .gitignore ├── pylint.sh ├── LICENSE ├── setup.py └── README.rst /tabel.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | tabel 2 | -------------------------------------------------------------------------------- /tabel.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tabel/_version.py: -------------------------------------------------------------------------------- 1 | __version__ = "1.2.3" 2 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 99 3 | -------------------------------------------------------------------------------- /tabel.egg-info/requires.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | tabulate 3 | -------------------------------------------------------------------------------- /docs/source/license.rst: -------------------------------------------------------------------------------- 1 | license 2 | ======= 3 | 4 | .. include:: ../../LICENSE 5 | -------------------------------------------------------------------------------- /docs/test.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/test.npz -------------------------------------------------------------------------------- /test/test.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/test/test.npz -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include LICENSE 3 | include README.rst 4 | include setup.py 5 | -------------------------------------------------------------------------------- /docs/build/html/_sources/license.rst.txt: -------------------------------------------------------------------------------- 1 | license 2 | ======= 3 | 4 | .. include:: ../../LICENSE 5 | -------------------------------------------------------------------------------- /docs/test.csv: -------------------------------------------------------------------------------- 1 | Name,Height,Married 2 | John,1.82,False 3 | Joe,1.65,False 4 | Jane,2.15,True 5 | -------------------------------------------------------------------------------- /test/.pytest_cache/v/cache/lastfailed: -------------------------------------------------------------------------------- 1 | { 2 | "test_tabel.py::TestShape_n_len::()::test_len": true 3 | } -------------------------------------------------------------------------------- /docs/build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/objects.inv -------------------------------------------------------------------------------- /docs/build/html/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/up.png -------------------------------------------------------------------------------- /test/.cache/v/cache/lastfailed: -------------------------------------------------------------------------------- 1 | { 2 | "test_tabel.py::TestDTypeProoperties::()::test_dtype_properties": true 3 | } -------------------------------------------------------------------------------- /docs/build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/index.doctree -------------------------------------------------------------------------------- /docs/build/html/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/down.png -------------------------------------------------------------------------------- /docs/build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/file.png -------------------------------------------------------------------------------- /docs/build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/minus.png -------------------------------------------------------------------------------- /docs/build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/plus.png -------------------------------------------------------------------------------- /docs/build/doctrees/license.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/license.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/readme.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/readme.doctree -------------------------------------------------------------------------------- /docs/build/html/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/comment.png -------------------------------------------------------------------------------- /docs/build/doctrees/api/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/api/index.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/api/module.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/api/module.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/api/tabel.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/api/tabel.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/cookbook.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/cookbook.doctree -------------------------------------------------------------------------------- /docs/build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/environment.pickle -------------------------------------------------------------------------------- /docs/build/html/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/up-pressed.png -------------------------------------------------------------------------------- /docs/build/doctrees/performance.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/doctrees/performance.doctree -------------------------------------------------------------------------------- /docs/build/html/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/build/html/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/down-pressed.png -------------------------------------------------------------------------------- /tabel/git_version.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | hashlabel = subprocess.check_output(["git", "rev-parse", "HEAD"]).strip().decode("utf-8") 3 | -------------------------------------------------------------------------------- /docs/build/html/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/build/html/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/comment-close.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .ipynb_checkpoints/ 3 | .DS_Store 4 | build/ 5 | .cache/ 6 | .pytest_cache/ 7 | dist/ 8 | example/ 9 | local_todo.rst 10 | -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-bold.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-bold.ttf -------------------------------------------------------------------------------- /docs/source/api/index.rst: -------------------------------------------------------------------------------- 1 | API Reference 2 | ============= 3 | 4 | .. toctree:: 5 | :maxdepth: 5 6 | 7 | 8 | module 9 | tabel 10 | -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-bold.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-bold.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-italic.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-italic.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-italic.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-italic.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-regular.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-regular.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-regular.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-regular.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/build/html/_sources/api/index.rst.txt: -------------------------------------------------------------------------------- 1 | API Reference 2 | ============= 3 | 4 | .. toctree:: 5 | :maxdepth: 5 6 | 7 | 8 | module 9 | tabel 10 | -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-bolditalic.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff -------------------------------------------------------------------------------- /docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BastiaanBergman/tabel/HEAD/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 -------------------------------------------------------------------------------- /docs/source/readme.rst: -------------------------------------------------------------------------------- 1 | .. image:: https://readthedocs.org/projects/tabel/badge/?version=latest 2 | :target: https://tabel.readthedocs.io/en/latest/?badge=latest 3 | :alt: Documentation Status 4 | 5 | .. include:: ../../README.rst 6 | -------------------------------------------------------------------------------- /docs/build/html/_sources/readme.rst.txt: -------------------------------------------------------------------------------- 1 | .. image:: https://readthedocs.org/projects/tabel/badge/?version=latest 2 | :target: https://tabel.readthedocs.io/en/latest/?badge=latest 3 | :alt: Documentation Status 4 | 5 | .. include:: ../../README.rst 6 | -------------------------------------------------------------------------------- /docs/build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 703750249707fe68aac37ef15b1944b9 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /pylint.sh: -------------------------------------------------------------------------------- 1 | echo "######## tabel.py" 2 | pylint tabel/tabel.py 3 | echo "######## hashjoin.py" 4 | pylint tabel/hashjoin.py 5 | echo "######## util.py" 6 | pylint tabel/util.py 7 | echo "######## numpy_types.py" 8 | pylint tabel/numpy_types.py 9 | echo "######## __init__.py" 10 | pylint tabel/__init__.py 11 | -------------------------------------------------------------------------------- /docs/source/api/module.rst: -------------------------------------------------------------------------------- 1 | tabel module 2 | ============ 3 | 4 | .. module:: tabel 5 | 6 | transpose 7 | --------- 8 | 9 | .. autofunction:: transpose 10 | 11 | .. autofunction:: T 12 | 13 | read_tabel 14 | ----------- 15 | 16 | .. autofunction:: read_tabel 17 | 18 | first 19 | ------ 20 | 21 | .. autofunction:: first 22 | -------------------------------------------------------------------------------- /docs/build/html/_sources/api/module.rst.txt: -------------------------------------------------------------------------------- 1 | tabel module 2 | ============ 3 | 4 | .. module:: tabel 5 | 6 | transpose 7 | --------- 8 | 9 | .. autofunction:: transpose 10 | 11 | .. autofunction:: T 12 | 13 | read_tabel 14 | ----------- 15 | 16 | .. autofunction:: read_tabel 17 | 18 | first 19 | ------ 20 | 21 | .. autofunction:: first 22 | -------------------------------------------------------------------------------- /docs/build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: 'v1.0', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | FILE_SUFFIX: '.html', 7 | HAS_SOURCE: true, 8 | SOURCELINK_SUFFIX: '.txt' 9 | }; -------------------------------------------------------------------------------- /test/.pytest_cache/README.md: -------------------------------------------------------------------------------- 1 | # pytest cache directory # 2 | 3 | This directory contains data from the pytest's cache plugin, 4 | which provides the `--lf` and `--ff` options, as well as the `cache` fixture. 5 | 6 | **Do not** commit this to version control. 7 | 8 | See [the docs](https://docs.pytest.org/en/latest/cache.html) for more information. 9 | -------------------------------------------------------------------------------- /tabel.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | LICENSE 2 | MANIFEST.in 3 | README.rst 4 | setup.py 5 | tabel/__init__.py 6 | tabel/_version.py 7 | tabel/git_version.py 8 | tabel/hashjoin.py 9 | tabel/numpy_types.py 10 | tabel/tabel.py 11 | tabel/util.py 12 | tabel.egg-info/PKG-INFO 13 | tabel.egg-info/SOURCES.txt 14 | tabel.egg-info/dependency_links.txt 15 | tabel.egg-info/requires.txt 16 | tabel.egg-info/top_level.txt 17 | test/test_tabel.py -------------------------------------------------------------------------------- /tabel/numpy_types.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | .. module:: tabel.numpy_types 4 | .. moduleauthor:: Bastiaan Bergman 5 | 6 | """ 7 | from __future__ import (absolute_import, division, print_function, 8 | unicode_literals) 9 | import numpy as np 10 | 11 | NP_FLOAT_TYPES = [np.float, np.float32, np.float64, np.float16] 12 | NP_INT_TYPES = [np.int, np.int32, np.int64] 13 | -------------------------------------------------------------------------------- /tabel/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | .. module:: tabel 4 | .. moduleauthor:: Bastiaan Bergman 5 | 6 | """ 7 | from .tabel import Tabel, read_tabel, transpose, T 8 | from .hashjoin import first 9 | from ._version import __version__ 10 | __all__ = ["Tabel", "first", "transpose", "T", "read_tabel", "__version__"] 11 | name = "tabel" # pylint: disable=invalid-name 12 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = -E -a 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = tabel 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. Tabel documentation master file, created by 2 | sphinx-quickstart on Wed Aug 8 20:31:28 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Tabel's documentation 7 | ===================== 8 | 9 | Tabel provides a lightweight and intuitive object for data tables, two 10 | dimensional tables with rows and columns. Based on Numpy, therefore fast and 11 | seamless integration with all the popular data tools. 12 | 13 | .. toctree:: 14 | :maxdepth: 6 15 | :caption: Contents: 16 | 17 | 18 | readme 19 | performance 20 | 21 | cookbook 22 | api/index 23 | 24 | license 25 | 26 | 27 | Indices and tables 28 | ================== 29 | 30 | * :ref:`genindex` 31 | * :ref:`modindex` 32 | * :ref:`search` 33 | -------------------------------------------------------------------------------- /docs/build/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | .. Tabel documentation master file, created by 2 | sphinx-quickstart on Wed Aug 8 20:31:28 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Tabel's documentation 7 | ===================== 8 | 9 | Tabel provides a lightweight and intuitive object for data tables, two 10 | dimensional tables with rows and columns. Based on Numpy, therefore fast and 11 | seamless integration with all the popular data tools. 12 | 13 | .. toctree:: 14 | :maxdepth: 6 15 | :caption: Contents: 16 | 17 | 18 | readme 19 | performance 20 | 21 | cookbook 22 | api/index 23 | 24 | license 25 | 26 | 27 | Indices and tables 28 | ================== 29 | 30 | * :ref:`genindex` 31 | * :ref:`modindex` 32 | * :ref:`search` 33 | -------------------------------------------------------------------------------- /tabel/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | .. module:: tabel.util 4 | .. moduleauthor:: Bastiaan Bergman 5 | 6 | """ 7 | from __future__ import (absolute_import, division, print_function, 8 | unicode_literals) 9 | import sys 10 | 11 | 12 | if sys.version_info >= (3, 0): 13 | PV = 3 14 | ImpError = ModuleNotFoundError # pylint: disable=invalid-name 15 | elif sys.version_info >= (2, 0): 16 | PV = 2 17 | ImpError = ImportError 18 | else: 19 | print("Forget about it!") 20 | sys.exit(1) 21 | 22 | def isstring(strng): 23 | """ Python version independent string checking """ 24 | if PV == 2: 25 | return isinstance(strng, basestring) # pylint: disable=undefined-variable 26 | if PV == 3: 27 | return isinstance(strng, str) 28 | raise NotImplementedError("Unknown python verison: {}".format(PV)) 29 | -------------------------------------------------------------------------------- /docs/build/doctest/output.txt: -------------------------------------------------------------------------------- 1 | Results of doctest builder run on 2019-08-15 15:39:27 2 | ===================================================== 3 | 4 | Document: api/tabel 5 | ------------------- 6 | 1 items passed all tests: 7 | 30 tests in default 8 | 30 tests in 1 items. 9 | 30 passed and 0 failed. 10 | Test passed. 11 | 12 | Document: cookbook 13 | ------------------ 14 | 1 items passed all tests: 15 | 82 tests in default 16 | 82 tests in 1 items. 17 | 82 passed and 0 failed. 18 | Test passed. 19 | 20 | Document: performance 21 | --------------------- 22 | 1 items passed all tests: 23 | 35 tests in default 24 | 35 tests in 1 items. 25 | 35 passed and 0 failed. 26 | Test passed. 27 | 28 | Document: readme 29 | ---------------- 30 | 1 items passed all tests: 31 | 32 tests in default 32 | 32 tests in 1 items. 33 | 32 passed and 0 failed. 34 | Test passed. 35 | 36 | Doctest summary 37 | =============== 38 | 179 tests 39 | 0 failures in tests 40 | 0 failures in setup code 41 | 0 failures in cleanup code 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2018] [Bastiaan Bergman] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | exec(open("tabel/_version.py").read()) 4 | 5 | with open("README.rst", "r") as fh: 6 | long_description = fh.read() 7 | 8 | setuptools.setup( 9 | name="tabel", 10 | keywords='data table', 11 | version=__version__, 12 | author="Bastiaan Bergman", 13 | author_email="Bastiaan.Bergman@gmail.com", 14 | description="Lightweight, intuitive and fast data-tables.", 15 | long_description=long_description, 16 | long_description_content_type="text/x-rst", 17 | url="https://github.com/BastiaanBergman/tabel", 18 | packages=setuptools.find_packages(), 19 | license='MIT', 20 | python_requires='>=2.6, >=3.0', 21 | install_requires=['numpy', 'tabulate'], 22 | classifiers=[ 23 | "Programming Language :: Python :: 3", 24 | "Programming Language :: Python :: 3.6", 25 | "Programming Language :: Python :: 2", 26 | "Programming Language :: Python :: 2.7", 27 | "License :: OSI Approved :: MIT License", 28 | "Operating System :: OS Independent", 29 | ], 30 | project_urls={ 31 | "Documentation": "https://tabel.readthedocs.io/en/stable/", 32 | "Source Code": "https://github.com/BastiaanBergman/tabel", 33 | } 34 | ) 35 | -------------------------------------------------------------------------------- /test/.pytest_cache/v/cache/nodeids: -------------------------------------------------------------------------------- 1 | [ 2 | "test_tabel.py::TestTabelInit::()::test_tabel_init", 3 | "test_tabel.py::TestAppend::()::test_append_tabel", 4 | "test_tabel.py::TestAppend::()::test_append_column", 5 | "test_tabel.py::TestAppend::()::test_append_combinations", 6 | "test_tabel.py::TestAppend::()::test_row_append_combinations", 7 | "test_tabel.py::TestSlice::()::test_slice_type", 8 | "test_tabel.py::TestSlice::()::test_slice_columns", 9 | "test_tabel.py::TestSlice::()::test_slice_rows", 10 | "test_tabel.py::TestSlice::()::test_slice_boolean", 11 | "test_tabel.py::TestSlice::()::test_slice_permiseable", 12 | "test_tabel.py::TestSetter::()::test_set_individual_elm", 13 | "test_tabel.py::TestSetter::()::test_set_column", 14 | "test_tabel.py::TestSetter::()::test_set_row", 15 | "test_tabel.py::TestSetter::()::test_add_column", 16 | "test_tabel.py::TestSetter::()::test_replace_column", 17 | "test_tabel.py::TestSaveNRead::()::test_save_and_read", 18 | "test_tabel.py::TestGroupBy::()::test_group_by", 19 | "test_tabel.py::TestShapeNLen::()::test_shape_n_len", 20 | "test_tabel.py::TestShapeNLen::()::test_shape", 21 | "test_tabel.py::TestShapeNLen::()::test_len", 22 | "test_tabel.py::TestTranspose::()::test_transpose", 23 | "test_tabel.py::TestJoin::()::test_inner_int_join", 24 | "test_tabel.py::TestJoin::()::test_inner_str_join", 25 | "test_tabel.py::TestJoin::()::test_outer_join", 26 | "test_tabel.py::TestSort::()::test_sort", 27 | "test_tabel.py::TestDTypeProperties::()::test_dtype_properties", 28 | "test_tabel.py::TestPandasBackAndForth::()::test_pandas_b_and_f" 29 | ] -------------------------------------------------------------------------------- /docs/source/api/tabel.rst: -------------------------------------------------------------------------------- 1 | class Tabel 2 | ============ 3 | 4 | .. currentmodule: tabel 5 | 6 | .. autoclass:: tabel.Tabel 7 | 8 | getter 9 | ------ 10 | 11 | .. automethod:: tabel.Tabel.__getitem__ 12 | 13 | setter 14 | ------ 15 | 16 | .. automethod:: tabel.Tabel.__setitem__ 17 | 18 | 19 | delitem 20 | ------- 21 | 22 | .. automethod:: tabel.Tabel.__delitem__ 23 | 24 | 25 | repr 26 | ---- 27 | 28 | .. automethod:: tabel.Tabel.__repr__ 29 | 30 | append 31 | ------ 32 | 33 | .. automethod:: tabel.Tabel.append 34 | 35 | row_append 36 | ---------- 37 | 38 | .. automethod:: tabel.Tabel.row_append 39 | 40 | join 41 | ----- 42 | 43 | .. automethod:: tabel.Tabel.join 44 | 45 | group_by 46 | -------- 47 | 48 | .. automethod:: tabel.Tabel.group_by 49 | 50 | sort 51 | ---- 52 | 53 | .. automethod:: tabel.Tabel.sort 54 | 55 | astype 56 | ------ 57 | 58 | .. automethod:: tabel.Tabel.astype 59 | 60 | save 61 | ---- 62 | 63 | .. automethod:: tabel.Tabel.save 64 | 65 | 66 | 67 | 68 | properties 69 | ----------- 70 | 71 | dict 72 | ~~~~ 73 | 74 | .. autoattribute:: tabel.Tabel.dict 75 | 76 | shape 77 | ~~~~~ 78 | 79 | .. autoattribute:: tabel.Tabel.shape 80 | 81 | len 82 | ~~~ 83 | 84 | .. autoattribute:: tabel.Tabel.__len__ 85 | 86 | dtype 87 | ~~~~~~ 88 | 89 | .. autoattribute:: tabel.Tabel.dtype 90 | 91 | valid 92 | ~~~~~~ 93 | 94 | .. autoattribute:: tabel.Tabel.valid 95 | 96 | 97 | class attributes 98 | ----------------- 99 | 100 | .. autoattribute:: tabel.Tabel.repr_layout 101 | 102 | .. autoattribute:: tabel.Tabel.max_repr_rows 103 | 104 | .. autoattribute:: tabel.Tabel.join_fill_value 105 | -------------------------------------------------------------------------------- /docs/build/html/_sources/api/tabel.rst.txt: -------------------------------------------------------------------------------- 1 | class Tabel 2 | ============ 3 | 4 | .. currentmodule: tabel 5 | 6 | .. autoclass:: tabel.Tabel 7 | 8 | getter 9 | ------ 10 | 11 | .. automethod:: tabel.Tabel.__getitem__ 12 | 13 | setter 14 | ------ 15 | 16 | .. automethod:: tabel.Tabel.__setitem__ 17 | 18 | 19 | delitem 20 | ------- 21 | 22 | .. automethod:: tabel.Tabel.__delitem__ 23 | 24 | 25 | repr 26 | ---- 27 | 28 | .. automethod:: tabel.Tabel.__repr__ 29 | 30 | append 31 | ------ 32 | 33 | .. automethod:: tabel.Tabel.append 34 | 35 | row_append 36 | ---------- 37 | 38 | .. automethod:: tabel.Tabel.row_append 39 | 40 | join 41 | ----- 42 | 43 | .. automethod:: tabel.Tabel.join 44 | 45 | group_by 46 | -------- 47 | 48 | .. automethod:: tabel.Tabel.group_by 49 | 50 | sort 51 | ---- 52 | 53 | .. automethod:: tabel.Tabel.sort 54 | 55 | astype 56 | ------ 57 | 58 | .. automethod:: tabel.Tabel.astype 59 | 60 | save 61 | ---- 62 | 63 | .. automethod:: tabel.Tabel.save 64 | 65 | 66 | 67 | 68 | properties 69 | ----------- 70 | 71 | dict 72 | ~~~~ 73 | 74 | .. autoattribute:: tabel.Tabel.dict 75 | 76 | shape 77 | ~~~~~ 78 | 79 | .. autoattribute:: tabel.Tabel.shape 80 | 81 | len 82 | ~~~ 83 | 84 | .. autoattribute:: tabel.Tabel.__len__ 85 | 86 | dtype 87 | ~~~~~~ 88 | 89 | .. autoattribute:: tabel.Tabel.dtype 90 | 91 | valid 92 | ~~~~~~ 93 | 94 | .. autoattribute:: tabel.Tabel.valid 95 | 96 | 97 | class attributes 98 | ----------------- 99 | 100 | .. autoattribute:: tabel.Tabel.repr_layout 101 | 102 | .. autoattribute:: tabel.Tabel.max_repr_rows 103 | 104 | .. autoattribute:: tabel.Tabel.join_fill_value 105 | -------------------------------------------------------------------------------- /docs/build/html/_static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} 2 | -------------------------------------------------------------------------------- /docs/build/html/_static/js/theme.js: -------------------------------------------------------------------------------- 1 | /* sphinx_rtd_theme version 0.4.1 | MIT license */ 2 | /* Built 20180727 10:07 */ 3 | require=function n(e,i,t){function o(s,a){if(!i[s]){if(!e[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(r)return r(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=i[s]={exports:{}};e[s][0].call(u.exports,function(n){var i=e[s][1][n];return o(i||n)},u,u.exports,n,e,i,t)}return i[s].exports}for(var r="function"==typeof require&&require,s=0;s"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var i=n(this);expand=n(''),expand.on("click",function(n){return e.toggleCurrent(i),n.stopPropagation(),!1}),i.prepend(expand)})},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),i=e.find('[href="'+n+'"]');if(0===i.length){var t=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(i=e.find('[href="#'+t.attr("id")+'"]')).length&&(i=e.find('[href="#"]'))}i.length>0&&($(".wy-menu-vertical .current").removeClass("current"),i.addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l1").parent().addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l2").addClass("current"),i.closest("li.toctree-l3").addClass("current"),i.closest("li.toctree-l4").addClass("current"))}catch(o){console.log("Error expanding nav for anchor",o)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,i=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(i),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],i=0;i 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Search — tabel v1.0 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 | 43 | 106 | 107 |
108 | 109 | 110 | 116 | 117 | 118 |
119 | 120 |
121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 |
139 | 140 |
    141 | 142 |
  • Docs »
  • 143 | 144 |
  • Search
  • 145 | 146 | 147 |
  • 148 | 149 | 150 | 151 |
  • 152 | 153 |
154 | 155 | 156 |
157 |
158 |
159 |
160 | 161 | 169 | 170 | 171 |
172 | 173 |
174 | 175 |
176 | 177 |
178 |
179 | 180 | 181 |
182 | 183 |
184 |

185 | © Copyright 2018, Bastiaan Bergman. 186 | 187 |

188 |
189 | Built with Sphinx using a theme provided by Read the Docs. 190 | 191 |
192 | 193 |
194 |
195 | 196 |
197 | 198 |
199 | 200 | 201 | 202 | 203 | 204 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 229 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /docs/build/html/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Python Module Index — tabel v1.0 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
48 | 49 | 50 | 113 | 114 |
115 | 116 | 117 | 123 | 124 | 125 |
126 | 127 |
128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 |
146 | 147 |
    148 | 149 |
  • Docs »
  • 150 | 151 |
  • Python Module Index
  • 152 | 153 | 154 |
  • 155 | 156 |
  • 157 | 158 |
159 | 160 | 161 |
162 |
163 |
164 |
165 | 166 | 167 |

Python Module Index

168 | 169 |
170 | t 171 |
172 | 173 | 174 | 175 | 177 | 178 | 179 | 182 |
 
176 | t
180 | tabel 181 |
183 | 184 | 185 |
186 | 187 |
188 |
189 | 190 | 191 |
192 | 193 |
194 |

195 | © Copyright 2018, Bastiaan Bergman. 196 | 197 |

198 |
199 | Built with Sphinx using a theme provided by Read the Docs. 200 | 201 |
202 | 203 |
204 |
205 | 206 |
207 | 208 |
209 | 210 | 211 | 212 | 213 | 214 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | import os 16 | import sys 17 | # sys.path.insert(0, os.path.abspath('../../')) 18 | # sys.path.insert(0, os.path.abspath('../../tabel')) 19 | # sys.path.insert(0, os.path.abspath('.')) 20 | # sys.path.insert(0, os.path.abspath('../')) 21 | sys.path.insert(0, os.path.abspath('../..')) 22 | # sys.path.insert(0, os.path.abspath('../tabel')) 23 | # APP_DIR = os.path.normpath(os.path.join(os.getcwd(), '../..')) 24 | # sys.path.insert(0, APP_DIR) 25 | # sys.path.insert(0, os.path.abspath('../tabel')) 26 | 27 | # import mock 28 | # 29 | # MOCK_MODULES = ['numpy', 'numpy.lib.recfunctions', 'itertools'] 30 | # for mod_name in MOCK_MODULES: 31 | # sys.modules[mod_name] = mock.Mock() 32 | 33 | # -- Project information ----------------------------------------------------- 34 | 35 | project = 'tabel' 36 | copyright = '2018, Bastiaan Bergman' 37 | author = 'Bastiaan Bergman' 38 | 39 | # The short X.Y version 40 | version = 'v1.0' 41 | # The full version, including alpha/beta/rc tags 42 | release = 'v1.0' 43 | 44 | 45 | 46 | # -- General configuration --------------------------------------------------- 47 | 48 | # If your documentation needs a minimal Sphinx version, state it here. 49 | # 50 | # needs_sphinx = '1.0' 51 | 52 | # Add any Sphinx extension module names here, as strings. They can be 53 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 54 | # ones. 55 | extensions = [ 56 | 'sphinx.ext.napoleon', 57 | # 'sphinx.ext.autodoc', 58 | 'sphinx.ext.doctest', 59 | # 'numpydoc', 60 | # 'sphinx.ext.napoleon', 61 | 'sphinx.ext.autosectionlabel', 62 | ] 63 | 64 | # numpydoc settings: 65 | # numpydoc_show_class_members = True 66 | # numpydoc_show_inherited_class_members = False 67 | # numpydoc_class_members_toctree = True 68 | 69 | # Napoleon settings 70 | napoleon_google_docstring = True 71 | napoleon_numpy_docstring = False 72 | # napoleon_include_init_with_doc = True 73 | # napoleon_include_private_with_doc = False 74 | napoleon_include_special_with_doc = True 75 | napoleon_use_admonition_for_examples = True 76 | napoleon_use_admonition_for_notes = True 77 | # napoleon_use_admonition_for_references = False 78 | napoleon_use_ivar = True 79 | napoleon_use_param = True 80 | # napoleon_use_rtype = True 81 | 82 | doctest_global_setup = """ 83 | from tabel import Tabel 84 | import numpy as np 85 | tbl = Tabel( [ ["John", "Joe", "Jane"],[1.82,1.65,2.15],[False,False,True] ],columns = ["Name", "Height", "Married"]) 86 | """ 87 | # Add any paths that contain templates here, relative to this directory. 88 | templates_path = ['_templates'] 89 | 90 | # The suffix(es) of source filenames. 91 | # You can specify multiple suffix as a list of string: 92 | # 93 | # source_suffix = ['.rst', '.md'] 94 | source_suffix = '.rst' 95 | 96 | # The master toctree document. 97 | master_doc = 'index' 98 | 99 | # The language for content autogenerated by Sphinx. Refer to documentation 100 | # for a list of supported languages. 101 | # 102 | # This is also used if you do content translation via gettext catalogs. 103 | # Usually you set "language" from the command line for these cases. 104 | language = None 105 | 106 | # List of patterns, relative to source directory, that match files and 107 | # directories to ignore when looking for source files. 108 | # This pattern also affects html_static_path and html_extra_path . 109 | exclude_patterns = [] 110 | 111 | # The name of the Pygments (syntax highlighting) style to use. 112 | pygments_style = 'sphinx' 113 | 114 | 115 | # -- Options for HTML output ------------------------------------------------- 116 | 117 | # The theme to use for HTML and HTML Help pages. See the documentation for 118 | # a list of builtin themes. 119 | # 120 | html_theme = 'sphinx_rtd_theme' 121 | 122 | # Theme options are theme-specific and customize the look and feel of a theme 123 | # further. For a list of options available for each theme, see the 124 | # documentation. 125 | # 126 | # html_theme_options = {} 127 | 128 | # Add any paths that contain custom static files (such as style sheets) here, 129 | # relative to this directory. They are copied after the builtin static files, 130 | # so a file named "default.css" will overwrite the builtin "default.css". 131 | html_static_path = ['_static'] 132 | 133 | # Custom sidebar templates, must be a dictionary that maps document names 134 | # to template names. 135 | # 136 | # The default sidebars (for documents that don't match any pattern) are 137 | # defined by theme itself. Builtin themes are using these templates by 138 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 139 | # 'searchbox.html']``. 140 | # 141 | # html_sidebars = {} 142 | 143 | 144 | # -- Options for HTMLHelp output --------------------------------------------- 145 | 146 | # Output file base name for HTML help builder. 147 | htmlhelp_basename = 'tabeldoc' 148 | 149 | 150 | # -- Options for LaTeX output ------------------------------------------------ 151 | 152 | latex_elements = { 153 | # The paper size ('letterpaper' or 'a4paper'). 154 | # 155 | # 'papersize': 'letterpaper', 156 | 157 | # The font size ('10pt', '11pt' or '12pt'). 158 | # 159 | # 'pointsize': '10pt', 160 | 161 | # Additional stuff for the LaTeX preamble. 162 | # 163 | # 'preamble': '', 164 | 165 | # Latex figure (float) alignment 166 | # 167 | # 'figure_align': 'htbp', 168 | } 169 | 170 | # Grouping the document tree into LaTeX files. List of tuples 171 | # (source start file, target name, title, 172 | # author, documentclass [howto, manual, or own class]). 173 | latex_documents = [ 174 | (master_doc, 'tabel.tex', 'tabel Documentation', 175 | 'Bastiaan Bergman', 'manual'), 176 | ] 177 | 178 | 179 | # -- Options for manual page output ------------------------------------------ 180 | 181 | # One entry per manual page. List of tuples 182 | # (source start file, name, description, authors, manual section). 183 | man_pages = [ 184 | (master_doc, 'tabel', 'tabel Documentation', 185 | [author], 1) 186 | ] 187 | 188 | 189 | # -- Options for Texinfo output ---------------------------------------------- 190 | 191 | # Grouping the document tree into Texinfo files. List of tuples 192 | # (source start file, target name, title, author, 193 | # dir menu entry, description, category) 194 | texinfo_documents = [ 195 | (master_doc, 'tabel', 'tabel Documentation', 196 | author, 'tabel', 'One line description of project.', 197 | 'Miscellaneous'), 198 | ] 199 | 200 | 201 | # -- Extension configuration ------------------------------------------------- 202 | -------------------------------------------------------------------------------- /docs/build/html/license.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | license — tabel v1.0 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 | 44 | 107 | 108 |
109 | 110 | 111 | 117 | 118 | 119 |
120 | 121 |
122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 |
140 | 141 |
    142 | 143 |
  • Docs »
  • 144 | 145 |
  • license
  • 146 | 147 | 148 |
  • 149 | 150 | 151 | View page source 152 | 153 | 154 |
  • 155 | 156 |
157 | 158 | 159 |
160 |
161 |
162 |
163 | 164 |
165 |

license

166 |

MIT License

167 |

Copyright (c) [2018] [Bastiaan Bergman]

168 |

Permission is hereby granted, free of charge, to any person obtaining a copy 169 | of this software and associated documentation files (the “Software”), to deal 170 | in the Software without restriction, including without limitation the rights 171 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 172 | copies of the Software, and to permit persons to whom the Software is 173 | furnished to do so, subject to the following conditions:

174 |

The above copyright notice and this permission notice shall be included in all 175 | copies or substantial portions of the Software.

176 |

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 177 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 179 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 180 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 181 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 182 | SOFTWARE.

183 |
184 | 185 | 186 |
187 | 188 |
189 |
190 | 191 | 197 | 198 | 199 |
200 | 201 |
202 |

203 | © Copyright 2018, Bastiaan Bergman. 204 | 205 |

206 |
207 | Built with Sphinx using a theme provided by Read the Docs. 208 | 209 |
210 | 211 |
212 |
213 | 214 |
215 | 216 |
217 | 218 | 219 | 220 | 221 | 222 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /docs/source/performance.rst: -------------------------------------------------------------------------------- 1 | Performance 2 | ============ 3 | 4 | Tabel is designed for those cases where you have data of multiple types, like 5 | records in a database, where the volume is small enough to fit it all in memory 6 | and high freedom of data manipulation is needed. Use Tabel when the following 7 | conditions are met: 8 | 9 | * Multiple columns with different datatyes each 10 | * Fields in a row have a shared relation (e.g. records in a database) 11 | * All data fits in memory 12 | * Only few and relatively simple SQL queries are needed 13 | * A large proportion of the data is numeric and would need column-wise 14 | arithmetic 15 | * Data manipulation requires complex (computed) slicing across both dimensions 16 | (rows and columns) 17 | 18 | If the above conditions are not met, consider these alternatives: 19 | 20 | * numpy - if your data is purely numerical or when fields in a row have no relation. 21 | * HDF5 - if your data does not fit in memory 22 | * SQLite or MySQL - if you need complex DB queries (e.g. transactional) 23 | 24 | That said, good general performance is paramount. Here below are some tests to 25 | give an rough overview of where Tabel stands relative to pandas. 26 | 27 | To do the tests, a few tools are needed: 28 | 29 | >>> import numpy as np 30 | >>> import pandas as pd 31 | >>> from tabel import Tabel 32 | >>> from timeit import default_timer 33 | 34 | 35 | slicing tables 36 | --------------- 37 | 38 | As Tabel is based on numpy, this is where it is good at. I think slicing syntax 39 | is both clean and fast (about 15x faster than pandas in the below tests). 40 | 41 | First slicing test is to get a whole row from a large table. The return 42 | value should be a tuple from Tabel, pandas produces an object array which I 43 | believe is not very efficient as columns usually have different datatypes. 44 | Tabel is abut 43x faster in this particular case: 45 | 46 | >>> n = 1000000 47 | >>> data_dict = {'a':[1,2,3,4] * n, 'b':['a1','a2']*2*n, 'c':np.arange(4*n)} 48 | >>> df = pd.DataFrame(data_dict) 49 | >>> tbl = Tabel(data_dict) 50 | >>> def test_pandas_slice(n): 51 | ... t0 = default_timer() 52 | ... for i in range(n): 53 | ... _ = df.iloc[100].values 54 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 55 | >>> test_pandas_slice(100000) # doctest: +SKIP 56 | (130.62096348032355, 'micro-sec') 57 | >>> def test_tabel_slice(n): 58 | ... t0 = default_timer() 59 | ... for i in range(n): 60 | ... _ = tbl[100] 61 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 62 | >>> test_tabel_slice(100000) # doctest: +SKIP 63 | (3.045091559179127, 'micro-sec') 64 | 65 | 66 | Second slicing test is to get a number of rows from one particular column, the 67 | return value should be an array. Tabel is abut 15x faster in this case: 68 | 69 | >>> def test_pandas_slice(n): 70 | ... t0 = default_timer() 71 | ... for i in range(n): 72 | ... _ = df['a'][1:10].values 73 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 74 | >>> test_pandas_slice(100000) # doctest: +SKIP 75 | (63.41531826881692, 'micro-sec') 76 | >>> def test_tabel_slice(n): 77 | ... t0 = default_timer() 78 | ... for i in range(n): 79 | ... _ = tbl[1:10, 'a'] 80 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 81 | >>> test_tabel_slice(100000) # doctest: +SKIP 82 | (4.007692479062825, 'micro-sec') 83 | 84 | 85 | appending rows 86 | -------------- 87 | 88 | I find myself often doing something similar to the following procedure: 89 | 90 | >>> for i in large_number: # doctest: +SKIP 91 | ... row = calculate_something() 92 | ... tbl.append(row) 93 | 94 | where "do something" could be reading some tricky formatted ascii file or 95 | calculating the position of the stars, it doesn't matter. The point is, 96 | appending data is never a very efficient thing to do, memory needs to be 97 | reserved, all values need to be re-evaluated for type setting and then all data 98 | gets copied over to the new location. Still I prefer this over more efficient 99 | methods as it keeps my code clean and simple. 100 | 101 | I expect bad performance for both Tabel and pandas, but a simple test shows that 102 | pandas is doing a bit worse. If we repeatedly add a simple row of two integers 103 | to a pandas DataFrame we'll use about 300 micro-second per row: 104 | 105 | >>> import pandas as pd 106 | >>> from tabel import Tabel 107 | >>> from timeit import default_timer 108 | >>> df = pd.DataFrame({'1':[],'2':[]}) 109 | >>> row = pd.DataFrame({'1':[1],'2':[2]}) 110 | >>> def test_pandas(n): 111 | ... t0 = default_timer() 112 | ... for i in range(n): 113 | ... df.append(row, ignore_index=True) 114 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 115 | >>> test_pandas(100000) # doctest: +SKIP 116 | (299.0699630905874, 'micro-sec') 117 | 118 | The same exercise with Tabel's :mod:`tabel.Tabel.row_append` method takes only a 119 | quarter of that time: 120 | 121 | >>> tbl = Tabel() 122 | >>> row = (1, 2) 123 | >>> def test_tabel(n): 124 | ... t0 = default_timer() 125 | ... for i in range(n): 126 | ... tbl.row_append(row) 127 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 128 | >>> test_tabel(100000) # doctest: +SKIP 129 | (79.83603572938591, 'micro-sec') 130 | 131 | Granted, there are very many different scenarios thinkable and there probably 132 | are scenarios where pandas would outperform Tabel. If you come across one of 133 | those please let me know and I happily add it here. 134 | 135 | 136 | grouping tables 137 | --------------- 138 | 139 | A big Tabel with a million rows can be grouped by multiple columns. Both pandas 140 | and Tabel take a good amount of time on this, but then this is typically done 141 | once on a an individual Tabel or DataFrame. pandas is about 10x faster than 142 | Tabel on this simple test. The good news is that this is independent of n, 143 | meaning they're both equally scalable. 144 | 145 | >>> n = 100000 146 | >>> data_dict = {'a':[1,2,3,4] * n, 'b':['a1','a2']*2*n, 'c':np.arange(4*n)} 147 | >>> df = pd.DataFrame(data_dict) 148 | >>> def test_pandas_groupby(n): 149 | ... t0 = default_timer() 150 | ... for i in range(n): 151 | ... _ = df.groupby(('a', 'b')).sum() 152 | ... return (default_timer() - t0)/n*1e3, "mili-sec" 153 | >>> test_pandas_groupby(10) # doctest: +SKIP 154 | (34.32465291116387, 'mili-sec') 155 | >>> tbl = Tabel(data_dict) 156 | >>> def test_tabel_groupby(n): 157 | ... t0 = default_timer() 158 | ... for i in range(n): 159 | ... _ = tbl.group_by(('b', 'a'),[(np.sum, 'c')]) 160 | ... return (default_timer() - t0)/n*1e3, "mili-sec" 161 | >>> test_tabel_groupby(10) # doctest: +SKIP 162 | (322.54316059406847, 'mili-sec') 163 | 164 | 165 | joining tables 166 | -------------- 167 | 168 | Two Tabels can be joined together by some common key present in both Tabels. Two 169 | table with a million rows takes about 2.5 second to be joined with pandas and 5 170 | times that with Tabel, this ratio reduces somewhat with n. See the codeblock 171 | below for the specific case tested here. 172 | 173 | >>> n = 1000000 174 | >>> data_dict = {'a':[1,2,3,4] * n, 'b':['a1','a2']*2*n, 'c':np.arange(4*n)} 175 | >>> df_1 = pd.DataFrame(data_dict) 176 | >>> df_2 = pd.DataFrame(data_dict) 177 | >>> def test_pandas_join(): 178 | ... t0 = default_timer() 179 | ... _ = df_1.join(df_2, on='c', how='inner', lsuffix='l', rsuffix='r') 180 | ... return (default_timer() - t0)*1e3, "mili-sec" 181 | >>> test_pandas_join() # doctest: +SKIP 182 | (2462.8482228145003, 'mili-sec') 183 | >>> tbl_1 = Tabel(data_dict) 184 | >>> tbl_2 = Tabel(data_dict) 185 | >>> def test_tabel_join(): 186 | ... t0 = default_timer() 187 | ... _ = tbl_1.join(tbl_2, key='c', jointype='inner') 188 | ... return (default_timer() - t0)*1e3, "mili-sec" 189 | >>> test_tabel_join() # doctest: +SKIP 190 | (10393.40596087277, 'mili-sec') 191 | -------------------------------------------------------------------------------- /docs/build/html/_sources/performance.rst.txt: -------------------------------------------------------------------------------- 1 | Performance 2 | ============ 3 | 4 | Tabel is designed for those cases where you have data of multiple types, like 5 | records in a database, where the volume is small enough to fit it all in memory 6 | and high freedom of data manipulation is needed. Use Tabel when the following 7 | conditions are met: 8 | 9 | * Multiple columns with different datatyes each 10 | * Fields in a row have a shared relation (e.g. records in a database) 11 | * All data fits in memory 12 | * Only few and relatively simple SQL queries are needed 13 | * A large proportion of the data is numeric and would need column-wise 14 | arithmetic 15 | * Data manipulation requires complex (computed) slicing across both dimensions 16 | (rows and columns) 17 | 18 | If the above conditions are not met, consider these alternatives: 19 | 20 | * numpy - if your data is purely numerical or when fields in a row have no relation. 21 | * HDF5 - if your data does not fit in memory 22 | * SQLite or MySQL - if you need complex DB queries (e.g. transactional) 23 | 24 | That said, good general performance is paramount. Here below are some tests to 25 | give an rough overview of where Tabel stands relative to pandas. 26 | 27 | To do the tests, a few tools are needed: 28 | 29 | >>> import numpy as np 30 | >>> import pandas as pd 31 | >>> from tabel import Tabel 32 | >>> from timeit import default_timer 33 | 34 | 35 | slicing tables 36 | --------------- 37 | 38 | As Tabel is based on numpy, this is where it is good at. I think slicing syntax 39 | is both clean and fast (about 15x faster than pandas in the below tests). 40 | 41 | First slicing test is to get a whole row from a large table. The return 42 | value should be a tuple from Tabel, pandas produces an object array which I 43 | believe is not very efficient as columns usually have different datatypes. 44 | Tabel is abut 43x faster in this particular case: 45 | 46 | >>> n = 1000000 47 | >>> data_dict = {'a':[1,2,3,4] * n, 'b':['a1','a2']*2*n, 'c':np.arange(4*n)} 48 | >>> df = pd.DataFrame(data_dict) 49 | >>> tbl = Tabel(data_dict) 50 | >>> def test_pandas_slice(n): 51 | ... t0 = default_timer() 52 | ... for i in range(n): 53 | ... _ = df.iloc[100].values 54 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 55 | >>> test_pandas_slice(100000) # doctest: +SKIP 56 | (130.62096348032355, 'micro-sec') 57 | >>> def test_tabel_slice(n): 58 | ... t0 = default_timer() 59 | ... for i in range(n): 60 | ... _ = tbl[100] 61 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 62 | >>> test_tabel_slice(100000) # doctest: +SKIP 63 | (3.045091559179127, 'micro-sec') 64 | 65 | 66 | Second slicing test is to get a number of rows from one particular column, the 67 | return value should be an array. Tabel is abut 15x faster in this case: 68 | 69 | >>> def test_pandas_slice(n): 70 | ... t0 = default_timer() 71 | ... for i in range(n): 72 | ... _ = df['a'][1:10].values 73 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 74 | >>> test_pandas_slice(100000) # doctest: +SKIP 75 | (63.41531826881692, 'micro-sec') 76 | >>> def test_tabel_slice(n): 77 | ... t0 = default_timer() 78 | ... for i in range(n): 79 | ... _ = tbl[1:10, 'a'] 80 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 81 | >>> test_tabel_slice(100000) # doctest: +SKIP 82 | (4.007692479062825, 'micro-sec') 83 | 84 | 85 | appending rows 86 | -------------- 87 | 88 | I find myself often doing something similar to the following procedure: 89 | 90 | >>> for i in large_number: # doctest: +SKIP 91 | ... row = calculate_something() 92 | ... tbl.append(row) 93 | 94 | where "do something" could be reading some tricky formatted ascii file or 95 | calculating the position of the stars, it doesn't matter. The point is, 96 | appending data is never a very efficient thing to do, memory needs to be 97 | reserved, all values need to be re-evaluated for type setting and then all data 98 | gets copied over to the new location. Still I prefer this over more efficient 99 | methods as it keeps my code clean and simple. 100 | 101 | I expect bad performance for both Tabel and pandas, but a simple test shows that 102 | pandas is doing a bit worse. If we repeatedly add a simple row of two integers 103 | to a pandas DataFrame we'll use about 300 micro-second per row: 104 | 105 | >>> import pandas as pd 106 | >>> from tabel import Tabel 107 | >>> from timeit import default_timer 108 | >>> df = pd.DataFrame({'1':[],'2':[]}) 109 | >>> row = pd.DataFrame({'1':[1],'2':[2]}) 110 | >>> def test_pandas(n): 111 | ... t0 = default_timer() 112 | ... for i in range(n): 113 | ... df.append(row, ignore_index=True) 114 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 115 | >>> test_pandas(100000) # doctest: +SKIP 116 | (299.0699630905874, 'micro-sec') 117 | 118 | The same exercise with Tabel's :mod:`tabel.Tabel.row_append` method takes only a 119 | quarter of that time: 120 | 121 | >>> tbl = Tabel() 122 | >>> row = (1, 2) 123 | >>> def test_tabel(n): 124 | ... t0 = default_timer() 125 | ... for i in range(n): 126 | ... tbl.row_append(row) 127 | ... return (default_timer() - t0)/n*1e6, "micro-sec" 128 | >>> test_tabel(100000) # doctest: +SKIP 129 | (79.83603572938591, 'micro-sec') 130 | 131 | Granted, there are very many different scenarios thinkable and there probably 132 | are scenarios where pandas would outperform Tabel. If you come across one of 133 | those please let me know and I happily add it here. 134 | 135 | 136 | grouping tables 137 | --------------- 138 | 139 | A big Tabel with a million rows can be grouped by multiple columns. Both pandas 140 | and Tabel take a good amount of time on this, but then this is typically done 141 | once on a an individual Tabel or DataFrame. pandas is about 10x faster than 142 | Tabel on this simple test. The good news is that this is independent of n, 143 | meaning they're both equally scalable. 144 | 145 | >>> n = 100000 146 | >>> data_dict = {'a':[1,2,3,4] * n, 'b':['a1','a2']*2*n, 'c':np.arange(4*n)} 147 | >>> df = pd.DataFrame(data_dict) 148 | >>> def test_pandas_groupby(n): 149 | ... t0 = default_timer() 150 | ... for i in range(n): 151 | ... _ = df.groupby(('a', 'b')).sum() 152 | ... return (default_timer() - t0)/n*1e3, "mili-sec" 153 | >>> test_pandas_groupby(10) # doctest: +SKIP 154 | (34.32465291116387, 'mili-sec') 155 | >>> tbl = Tabel(data_dict) 156 | >>> def test_tabel_groupby(n): 157 | ... t0 = default_timer() 158 | ... for i in range(n): 159 | ... _ = tbl.group_by(('b', 'a'),[(np.sum, 'c')]) 160 | ... return (default_timer() - t0)/n*1e3, "mili-sec" 161 | >>> test_tabel_groupby(10) # doctest: +SKIP 162 | (322.54316059406847, 'mili-sec') 163 | 164 | 165 | joining tables 166 | -------------- 167 | 168 | Two Tabels can be joined together by some common key present in both Tabels. Two 169 | table with a million rows takes about 2.5 second to be joined with pandas and 5 170 | times that with Tabel, this ratio reduces somewhat with n. See the codeblock 171 | below for the specific case tested here. 172 | 173 | >>> n = 1000000 174 | >>> data_dict = {'a':[1,2,3,4] * n, 'b':['a1','a2']*2*n, 'c':np.arange(4*n)} 175 | >>> df_1 = pd.DataFrame(data_dict) 176 | >>> df_2 = pd.DataFrame(data_dict) 177 | >>> def test_pandas_join(): 178 | ... t0 = default_timer() 179 | ... _ = df_1.join(df_2, on='c', how='inner', lsuffix='l', rsuffix='r') 180 | ... return (default_timer() - t0)*1e3, "mili-sec" 181 | >>> test_pandas_join() # doctest: +SKIP 182 | (2462.8482228145003, 'mili-sec') 183 | >>> tbl_1 = Tabel(data_dict) 184 | >>> tbl_2 = Tabel(data_dict) 185 | >>> def test_tabel_join(): 186 | ... t0 = default_timer() 187 | ... _ = tbl_1.join(tbl_2, key='c', jointype='inner') 188 | ... return (default_timer() - t0)*1e3, "mili-sec" 189 | >>> test_tabel_join() # doctest: +SKIP 190 | (10393.40596087277, 'mili-sec') 191 | -------------------------------------------------------------------------------- /docs/build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["api/index","api/module","api/tabel","cookbook","index","license","performance","readme"],envversion:53,filenames:["api/index.rst","api/module.rst","api/tabel.rst","cookbook.rst","index.rst","license.rst","performance.rst","readme.rst"],objects:{"":{tabel:[1,0,0,"-"]},"tabel.Tabel":{__delitem__:[2,3,1,""],__getitem__:[2,3,1,""],__len__:[2,4,1,""],__repr__:[2,3,1,""],__setitem__:[2,3,1,""],append:[2,3,1,""],astype:[2,3,1,""],dict:[2,4,1,""],dtype:[2,4,1,""],group_by:[2,3,1,""],join:[2,3,1,""],join_fill_value:[2,4,1,""],max_repr_rows:[2,4,1,""],repr_layout:[2,4,1,""],row_append:[2,3,1,""],save:[2,3,1,""],shape:[2,4,1,""],sort:[2,3,1,""],valid:[2,4,1,""]},tabel:{T:[1,1,1,""],Tabel:[2,2,1,""],first:[1,1,1,""],read_tabel:[1,1,1,""],transpose:[1,1,1,""]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","method","Python method"],"4":["py","attribute","Python attribute"]},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:method","4":"py:attribute"},terms:{"10x":6,"15x":6,"1e3":6,"1e6":6,"43x":6,"boolean":[2,3],"case":[2,3,6,7],"class":[0,4],"default":[2,7],"final":3,"float":2,"function":[1,2,3,7],"import":[2,3,6,7],"int":2,"long":3,"new":[2,3,6,7],"return":[1,2,3,6,7],"ta\u02d0\u02c8b\u025bl":[],"true":[1,2,3,6,7],"try":[1,7],"while":[2,3],AND:5,Added:7,Adding:7,BUT:5,Bas:3,FOR:5,For:[2,7],Jos:[3,7],NOT:5,Not:2,One:2,THE:5,That:6,The:[1,2,3,5,6,7],There:3,USE:5,Use:[2,6],Using:[2,3,7],WITH:5,With:7,__delitem__:[2,7],__getitem__:[2,3,7],__len__:2,__repr__:[2,7],__setitem__:[2,3,7],a_sum:[2,3],about:[1,4,6],abov:[5,6],abscent:2,abut:6,access:7,accord:2,across:6,action:5,activ:7,actual:7,add:[2,3,6,7],added:2,adding:2,addit:7,address:[2,3],adit:2,adjust:7,adress:2,affectd:2,again:[],aggreg:[2,3],aggregate_fie_col:2,agreg:2,alia:1,all:[2,3,4,5,6,7],allow:[2,7],along:2,alreadi:7,also:[2,3],altern:[6,7],alwai:[2,3,7],amount:6,analog:7,ani:[2,3,5],anoth:[3,7],answer:7,anyth:[1,2],api:[3,4,7],append:[0,4],appli:2,approxim:[2,3],arang:6,argument:[1,2,3,7],aris:5,arithmet:[3,6],arrai:[1,2,3,6,7],ascii:6,ass:7,associ:5,assum:1,astyp:[0,4],attribut:[0,4],author:5,auto:[1,2],automat:[2,7],avail:3,b_l:[2,3],back:[3,7],bad:6,base:[4,6],basic:7,bastiaan:[5,7],bastiaanbergman:7,bdist_wheel:7,becaus:2,believ:6,below:6,bergman:[5,7],besid:2,best:7,between:2,big:6,binari:2,bit:6,blanklin:3,bmi:3,bool:[1,2,7],both:[2,3,6,7],buffer:7,c_first:[2,3],c_r:[2,3],cach:7,calcul:[6,7],calculate_someth:6,call:[2,3],can:[2,3,6,7],cell:7,chang:[2,4],charact:7,charg:5,check:[2,3,7],choic:7,claim:5,clean:6,code:6,codeblock:6,collect:[],colum:[2,3],column:[1,2,4,6,7],columnnam:2,com:7,combin:3,come:[2,3,6,7],common:[2,3,6],complex:6,complic:7,compress:2,comput:6,concaten:7,conda:7,condit:[5,6],connect:5,connector:[1,3,7],consid:[2,6],constructor:2,contain:[1,2],content:4,contract:5,contribut:4,contributor:4,conveni:[1,2,3,7],convent:2,convert:[2,7],cookbook:4,copi:[2,3,5,6,7],copyright:5,could:[2,6],coumn:2,creat:[2,7],csv:[1,2,3,7],current:2,damag:5,data:[1,2,3,4,6,7],data_dict:6,databas:[2,3,6,7],datafram:[2,6,7],datalogg:7,datastruct:[1,2],datastructur:2,datat:7,dataty:6,datatyp:[1,2,3,6,7],datetim:7,dbase:2,deal:5,def:6,default_tim:6,del:2,delet:[2,7],delitem:[0,4],depend:[2,4],descript:[3,7],design:[4,6],destin:2,detail:3,determin:2,deviat:7,df_1:6,df_2:6,dict:[0,3,4,7],dictionari:[3,7],differ:[2,3,6,7],dimens:6,dimension:[4,7],dinner:7,directli:[2,3],directori:2,disk:[1,3,7],dist:7,distinct:7,distribut:5,doc:7,doctest:[6,7],document:[3,5,7],doe:[2,6,7],doesn:6,doing:[1,2,6],don:7,done:[2,6,7],dtype:[0,4,7],dump:2,dutch:7,each:[1,2,6,7],easi:7,effici:6,either:2,element:[1,2,3,7],empti:[2,3],end:[2,3],enforc:7,english:7,enhanc:7,enlist:7,enough:6,environ:7,equal:[3,6],equival:3,error:7,etc:7,evalu:6,event:5,exampl:[1,3,7],except:[2,3,7],exercis:6,exist:[2,3],expect:[1,2,6,7],explicitli:7,express:5,extens:[1,2],fals:[1,2,3,7],fashion:7,fast:[4,6,7],faster:[6,7],featur:7,few:6,fiel:2,field:6,file:[2,5,6,7],filenam:[1,2],filetyp:2,fill:2,find:6,first:[0,2,3,4,6,7],fit:[5,6],fix:[2,7],fmt:[1,2,3],focuss:7,follow:[2,5,6],foo:3,format:[1,2,3,6,7],forth:7,four:2,framework:7,free:5,freedom:6,from:[1,2,3,5,6,7],frustrat:7,full:[2,7],fundament:7,furnish:5,further:7,futur:7,gener:[2,3,6,7],get:[1,2,3,4,6],getter:[0,4],github:7,give:[2,3,6,7],given:3,gmail:7,going:7,good:6,got:7,grant:[5,6],group:[2,4,7],group_bi:[0,1,3,4,6,7],groupbi:6,gzip:2,happili:6,has:2,have:[2,3,6,7],hdf5:6,header:[1,2,7],height:[2,3,7],help:4,here:6,herebi:5,high:6,holder:5,how:[2,3,6],howev:[2,3],html:7,http:7,ignor:2,ignore_index:6,iloc:[6,7],implement:2,impli:5,includ:[1,2,3,5],ind:2,independ:6,index:[2,3,4,7],indexerror:2,indic:[2,3],individu:[1,3,6],init:4,initi:[2,4,7],inner:[2,6],input:2,instal:4,instanc:[2,4],instead:3,integ:[2,3,6],integr:[4,7],interfac:7,intern:[1,2],intuit:[4,7],invalid:2,invallid:2,invok:2,issu:7,item:7,iter:2,its:[2,3,7],itself:7,jack:[3,7],jane:[2,3,7],job:7,joe:[2,3,7],john:[2,3,7],join:[0,4,7],join_fill_valu:2,jointyp:[2,6],jupyt:7,just:[2,3,7],keep:6,kei:[2,3,6,7],key_r:2,keyerror:2,keyword:2,kid:7,kind:5,know:6,larg:6,large_numb:6,later:2,layout:2,left:[2,3,7],legit:2,len:[0,3,4,7],length:[2,3],let:6,liabil:5,liabl:5,licens:4,lightweight:[4,7],like:[2,6,7],limit:[5,7],line:2,list:[1,2,3,7],loc:7,locat:[2,6],logic:7,lsuffix:6,machineri:7,made:2,make:[2,3,7],mani:[6,7],manipul:[2,3,6,7],marri:[2,3,7],match:2,matter:6,max_repr_row:2,maximum:2,mean:[6,7],memori:[2,6],merchant:5,merg:5,mess:7,messag:7,met:6,method:[2,3,6,7],micro:6,mili:6,million:6,mit:5,modifi:[3,5],modul:[0,2,4,7],monitor:7,more:[2,6,7],mostli:[2,7],multi:7,multipl:6,myself:6,mysql:6,name:[2,4],nan:2,nativ:[2,3],ndarrai:[1,2],necess:7,need:[2,6,7],never:[2,6],newer:3,none:[1,2,7],noninfring:5,note:3,noteabl:[2,3],noth:2,notic:5,npz:[1,2,3],number:[2,6,7],numer:6,numpi:[1,2,3,4,6,7],object:[1,2,3,4,6],obtain:[3,5],often:[3,6],old:7,omit:[2,3],ommit:2,onc:[6,7],one:[2,3,6,7],onject:2,onli:[1,2,6,7],oper:2,option:7,order:[2,3],origin:[2,3],other:[2,3,5,7],otherwis:5,out:[2,3,5],outer:2,outerjoin:7,outperform:6,over:6,overview:6,overweght:3,own:[2,7],page:4,panda:[2,4,6],paramet:[1,2],paramount:6,part:[2,3],particular:[5,6,7],path:[1,2],per:[2,6],perfect:7,perform:[2,4,7],permiss:5,permit:5,person:5,pip:7,place:2,pleas:6,point:[2,6],polish:7,pop_column:7,popular:[4,7],portion:5,posit:[3,6],possib:2,possibl:2,prefer:6,present:[2,6],presto:2,pretti:2,print:2,priori:1,probabl:6,procedur:6,produc:6,properti:[0,3,4],proport:6,propos:7,provid:[2,3,4,5,7],publish:5,pure:6,purpos:5,py27_180412:[],py2_7:7,py36_180417:[],py3_6:7,pylint:7,pypi:7,pytest:7,python:[2,7],quarter:6,queri:6,question:7,quickstart:4,rais:[2,7],rang:[2,3,6,7],rather:7,ratio:6,read:[1,4,6,7],read_tabel:[0,3,4],real:7,reccord:2,recommend:[3,7],record:[1,2,3,6,7],reduc:6,refer:[2,3,4,7],referenc:[2,4],reflect:2,rel:6,relat:[2,6],releas:4,remain:3,remov:[2,7],renam:2,reorder:3,repeat:2,repeatedli:6,replac:[2,3],replic:2,repositori:7,repr:[0,4],repr_layout:2,request:[2,7],requir:[2,6],reserv:6,resourc:4,respect:2,restrict:5,result:[2,3,7],right:[2,5],rough:6,row:[1,2,4],row_append:[0,3,4,6,7],row_item:7,rsuffix:6,rtd:7,rule:2,said:6,same:[2,3,6,7],save:[0,4,7],scalabl:6,scenario:6,sdist:7,seamless:4,search:4,sec:6,seccond:[2,3],second:[3,6],see:[1,2,3,6,7],seem:7,sell:5,separ:3,septemb:7,seri:7,set:[2,4,6],setter:[0,4],setup:7,setuptool:7,shall:5,shape:[0,3,4,7],share:6,should:[2,3,6,7],show:[2,3,6],signific:[],similar:6,simpl:[6,7],simpli:7,simplifi:7,singl:[2,3],size:7,skip:[6,7],slice:[2,4],small:6,snif:7,sniff:1,softwar:5,some:[3,6],someth:6,somewhat:6,sort:[0,4,7],spars:7,specif:[2,6],specifi:[1,2,7],sphynx:7,sql:6,sqlite:6,sring:1,stabl:4,stackoverflow:7,stai:[2,3],stand:6,standard:[2,3],star:6,still:[2,6],store:[1,2,7],str:[1,2],string:2,structur:2,style:2,subject:5,sublicens:5,subset:[1,7],substanti:5,suffix:2,sum:[2,3,6],suppli:[2,7],support:[1,2,7],syntax:[2,3,6,7],tabe:3,tabel:[0,6],tabl:[2,3,7],tabul:[2,7],tafel:7,take:[1,2,3,6],target:2,tbl:[2,3,6,7],tbl_1:6,tbl_2:6,tbl_b:[2,3],tbl_r:2,tblb:3,temp:7,test:[3,4,6],test_panda:6,test_pandas_groupbi:6,test_pandas_join:6,test_pandas_slic:6,test_tabel:6,test_tabel_groupbi:6,test_tabel_join:6,test_tabel_slic:6,than:[2,3,6],thei:[6,7],them:3,therefor:[3,4],thi:[1,2,5,6,7],thing:6,think:6,thinkabl:6,those:6,three:7,through:2,thrown:2,time:6,timeit:6,todo:4,togeth:[2,6],too:3,tool:[4,6,7],tort:5,tox:7,transact:6,transfer:2,translat:7,transpos:[0,2,4,7],treat:2,tricki:6,tupl:[1,2,3,6,7],twice:[],twine:7,two:[2,3,4,6,7],type:[2,3,6,7],typic:6,unicod:7,uniqu:3,unless:2,unsupport:7,upload:7,use:[2,3,5,6,7],used:[1,2,3,7],useful:2,user:7,using:[2,3,7],usual:[1,6,7],valid:[0,4,7],vallu:2,valu:[2,6,7],valueerror:2,variou:3,varyiabl:2,veri:[6,7],volum:6,wai:7,want:7,warn:7,warranti:5,well:[2,3,7],wether:2,what:4,when:[1,2,3,6,7],where:[2,6],whether:[1,2,5,7],which:[2,6,7],whole:[2,3,6,7],whom:5,wich:2,wide:7,width:7,wiktionari:7,wise:6,without:[1,5],word:7,work:[3,7],wors:6,would:[3,6,7],write:[2,7],you:[3,6],your:[6,7],zero:2,zip:2},titles:["API Reference","tabel module","class Tabel","Cookbook","Tabel\u2019s documentation","license","Performance","About Tabel"],titleterms:{"class":2,about:7,api:0,append:[2,3,6,7],astyp:2,attribut:2,chang:3,column:3,contribut:7,contributor:7,cookbook:3,delitem:2,depend:7,design:7,dict:2,document:4,dtype:2,exampl:2,first:1,get:7,getter:2,group:[3,6],group_bi:2,help:7,indic:4,init:7,initi:3,instal:7,instanc:7,join:[2,3,6],len:2,licens:5,modul:1,name:[3,7],note:2,object:7,panda:7,perform:6,properti:[2,7],quickstart:7,read:3,read_tabel:1,refer:0,referenc:3,releas:7,repr:2,resourc:7,row:[3,6,7],row_append:2,save:[2,3],set:[3,7],setter:2,shape:2,slice:[3,6,7],sort:[2,3],stabl:7,tabel:[1,2,3,4,7],tabl:[4,6],test:7,todo:7,transpos:[1,3],valid:2,what:7}}) -------------------------------------------------------------------------------- /docs/build/html/api/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | API Reference — tabel v1.0 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 112 | 113 |
114 | 115 | 116 | 122 | 123 | 124 |
125 | 126 |
127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 |
145 | 146 |
    147 | 148 |
  • Docs »
  • 149 | 150 |
  • API Reference
  • 151 | 152 | 153 |
  • 154 | 155 | 156 | View page source 157 | 158 | 159 |
  • 160 | 161 |
162 | 163 | 164 |
165 |
166 |
167 |
168 | 169 |
170 |

API Reference

171 |
172 | 203 |
204 |
205 | 206 | 207 |
208 | 209 |
210 |
211 | 212 | 220 | 221 | 222 |
223 | 224 |
225 |

226 | © Copyright 2018, Bastiaan Bergman. 227 | 228 |

229 |
230 | Built with Sphinx using a theme provided by Read the Docs. 231 | 232 |
233 | 234 |
235 |
236 | 237 |
238 | 239 |
240 | 241 | 242 | 243 | 244 | 245 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 269 | 270 | 271 | -------------------------------------------------------------------------------- /docs/build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s === 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node, addItems) { 70 | if (node.nodeType === 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && 74 | !jQuery(node.parentNode).hasClass(className) && 75 | !jQuery(node.parentNode).hasClass("nohighlight")) { 76 | var span; 77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 78 | if (isInSVG) { 79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 80 | } else { 81 | span = document.createElement("span"); 82 | span.className = className; 83 | } 84 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 86 | document.createTextNode(val.substr(pos + text.length)), 87 | node.nextSibling)); 88 | node.nodeValue = val.substr(0, pos); 89 | if (isInSVG) { 90 | var bbox = span.getBBox(); 91 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 92 | rect.x.baseVal.value = bbox.x; 93 | rect.y.baseVal.value = bbox.y; 94 | rect.width.baseVal.value = bbox.width; 95 | rect.height.baseVal.value = bbox.height; 96 | rect.setAttribute('class', className); 97 | var parentOfText = node.parentNode.parentNode; 98 | addItems.push({ 99 | "parent": node.parentNode, 100 | "target": rect}); 101 | } 102 | } 103 | } 104 | else if (!jQuery(node).is("button, select, textarea")) { 105 | jQuery.each(node.childNodes, function() { 106 | highlight(this, addItems); 107 | }); 108 | } 109 | } 110 | var addItems = []; 111 | var result = this.each(function() { 112 | highlight(this, addItems); 113 | }); 114 | for (var i = 0; i < addItems.length; ++i) { 115 | jQuery(addItems[i].parent).before(addItems[i].target); 116 | } 117 | return result; 118 | }; 119 | 120 | /* 121 | * backward compatibility for jQuery.browser 122 | * This will be supported until firefox bug is fixed. 123 | */ 124 | if (!jQuery.browser) { 125 | jQuery.uaMatch = function(ua) { 126 | ua = ua.toLowerCase(); 127 | 128 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 129 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 130 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 131 | /(msie) ([\w.]+)/.exec(ua) || 132 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 133 | []; 134 | 135 | return { 136 | browser: match[ 1 ] || "", 137 | version: match[ 2 ] || "0" 138 | }; 139 | }; 140 | jQuery.browser = {}; 141 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 142 | } 143 | 144 | /** 145 | * Small JavaScript module for the documentation. 146 | */ 147 | var Documentation = { 148 | 149 | init : function() { 150 | this.fixFirefoxAnchorBug(); 151 | this.highlightSearchWords(); 152 | this.initIndexTable(); 153 | 154 | }, 155 | 156 | /** 157 | * i18n support 158 | */ 159 | TRANSLATIONS : {}, 160 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 161 | LOCALE : 'unknown', 162 | 163 | // gettext and ngettext don't access this so that the functions 164 | // can safely bound to a different name (_ = Documentation.gettext) 165 | gettext : function(string) { 166 | var translated = Documentation.TRANSLATIONS[string]; 167 | if (typeof translated === 'undefined') 168 | return string; 169 | return (typeof translated === 'string') ? translated : translated[0]; 170 | }, 171 | 172 | ngettext : function(singular, plural, n) { 173 | var translated = Documentation.TRANSLATIONS[singular]; 174 | if (typeof translated === 'undefined') 175 | return (n == 1) ? singular : plural; 176 | return translated[Documentation.PLURALEXPR(n)]; 177 | }, 178 | 179 | addTranslations : function(catalog) { 180 | for (var key in catalog.messages) 181 | this.TRANSLATIONS[key] = catalog.messages[key]; 182 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 183 | this.LOCALE = catalog.locale; 184 | }, 185 | 186 | /** 187 | * add context elements like header anchor links 188 | */ 189 | addContextElements : function() { 190 | $('div[id] > :header:first').each(function() { 191 | $('\u00B6'). 192 | attr('href', '#' + this.id). 193 | attr('title', _('Permalink to this headline')). 194 | appendTo(this); 195 | }); 196 | $('dt[id]').each(function() { 197 | $('\u00B6'). 198 | attr('href', '#' + this.id). 199 | attr('title', _('Permalink to this definition')). 200 | appendTo(this); 201 | }); 202 | }, 203 | 204 | /** 205 | * workaround a firefox stupidity 206 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 207 | */ 208 | fixFirefoxAnchorBug : function() { 209 | if (document.location.hash && $.browser.mozilla) 210 | window.setTimeout(function() { 211 | document.location.href += ''; 212 | }, 10); 213 | }, 214 | 215 | /** 216 | * highlight the search words provided in the url in the text 217 | */ 218 | highlightSearchWords : function() { 219 | var params = $.getQueryParameters(); 220 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 221 | if (terms.length) { 222 | var body = $('div.body'); 223 | if (!body.length) { 224 | body = $('body'); 225 | } 226 | window.setTimeout(function() { 227 | $.each(terms, function() { 228 | body.highlightText(this.toLowerCase(), 'highlighted'); 229 | }); 230 | }, 10); 231 | $('') 233 | .appendTo($('#searchbox')); 234 | } 235 | }, 236 | 237 | /** 238 | * init the domain index toggle buttons 239 | */ 240 | initIndexTable : function() { 241 | var togglers = $('img.toggler').click(function() { 242 | var src = $(this).attr('src'); 243 | var idnum = $(this).attr('id').substr(7); 244 | $('tr.cg-' + idnum).toggle(); 245 | if (src.substr(-9) === 'minus.png') 246 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 247 | else 248 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 249 | }).css('display', ''); 250 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 251 | togglers.click(); 252 | } 253 | }, 254 | 255 | /** 256 | * helper function to hide the search marks again 257 | */ 258 | hideSearchWords : function() { 259 | $('#searchbox .highlight-link').fadeOut(300); 260 | $('span.highlighted').removeClass('highlighted'); 261 | }, 262 | 263 | /** 264 | * make the url absolute 265 | */ 266 | makeURL : function(relativeURL) { 267 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 268 | }, 269 | 270 | /** 271 | * get the current relative url 272 | */ 273 | getCurrentURL : function() { 274 | var path = document.location.pathname; 275 | var parts = path.split(/\//); 276 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 277 | if (this === '..') 278 | parts.pop(); 279 | }); 280 | var url = parts.join('/'); 281 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 282 | }, 283 | 284 | initOnKeyListeners: function() { 285 | $(document).keyup(function(event) { 286 | var activeElementType = document.activeElement.tagName; 287 | // don't navigate when in search box or textarea 288 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { 289 | switch (event.keyCode) { 290 | case 37: // left 291 | var prevHref = $('link[rel="prev"]').prop('href'); 292 | if (prevHref) { 293 | window.location.href = prevHref; 294 | return false; 295 | } 296 | case 39: // right 297 | var nextHref = $('link[rel="next"]').prop('href'); 298 | if (nextHref) { 299 | window.location.href = nextHref; 300 | return false; 301 | } 302 | } 303 | } 304 | }); 305 | } 306 | }; 307 | 308 | // quick alias for translations 309 | _ = Documentation.gettext; 310 | 311 | $(document).ready(function() { 312 | Documentation.init(); 313 | }); -------------------------------------------------------------------------------- /tabel/hashjoin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | .. module:: tabel.hashjoin 4 | .. moduleauthor:: Bastiaan Bergman 5 | 6 | """ 7 | from __future__ import (absolute_import, division, print_function, 8 | unicode_literals) 9 | from collections import defaultdict 10 | import numpy as np 11 | from .numpy_types import * # pylint: disable=wildcard-import 12 | from .util import isstring 13 | 14 | def arg_hash(arlst): 15 | """Return defaultdict with list of rownumbers 16 | """ 17 | keylist = defaultdict(list) 18 | for i, elem in enumerate(zip(*(arlst))): 19 | keylist[elem].append(i) 20 | return keylist 21 | 22 | def arg_left_join(tbl_l, index1, tbl_r, index2): 23 | """Join and return _column_indices 24 | """ 25 | hash_r = arg_hash(tbl_r[:, index2].data) 26 | idx = np.array([(s, i) for i, r in enumerate(zip(*tbl_l[:, index1].data)) 27 | for s in hash_r.get(r, [-1])]) 28 | return idx 29 | 30 | def add_empty_row(tbl): 31 | """Add an empty row using the fill values to the end of an Tabel 32 | """ 33 | empty_row = [] 34 | for c in tbl.dtype.names: 35 | if tbl.dtype[c] in NP_FLOAT_TYPES: 36 | empty_row.append(tbl.join_fill_value['float']) 37 | if tbl.dtype[c].kind in {'U', 'S'}: 38 | empty_row.append(tbl.join_fill_value['string']) 39 | if tbl.dtype[c] in NP_INT_TYPES: 40 | empty_row.append(tbl.join_fill_value['integer']) 41 | try: 42 | tbl.row_append(empty_row) 43 | except ValueError: 44 | raise ValueError("Outer join cannot be fullfilled when there are other ", 45 | "columns than float, string or integer because Tabel ", 46 | "doesn't know what to fill it up with.") 47 | 48 | def remove_empty_row(tbl): 49 | """Remove the last (emtpy) row of a Tabel, used for outer joins 50 | """ 51 | tbl.data = [dt[0:-1] for dt in tbl.data] 52 | 53 | 54 | class HashJoinMixin(object): 55 | """Mixin to add to the Tabel class, providing join and group_by methods 56 | """ 57 | 58 | def _union(self, idx, key, tbl_r, key_r, jointype="inner", suffixes=("_l", "_r")): 59 | """Put together the final output based on indices. 60 | """ 61 | col_l = [c for c in self.columns if c not in key] 62 | col_r = [c for c in tbl_r.columns if c not in key_r] 63 | 64 | if jointype in ("inner", "left"): 65 | columns = (key + [c+suffixes[0] for c in col_l] + 66 | [c+suffixes[1] for c in col_r]) 67 | col_l = key + col_l 68 | elif jointype == "outer": 69 | col_l = key + col_l 70 | col_r = key_r + col_r 71 | columns = ([c+suffixes[0] for c in col_l] + 72 | [c+suffixes[1] for c in col_r]) 73 | elif jointype == "right": 74 | columns = ([c+suffixes[0] for c in col_l] + 75 | key_r + [c+suffixes[1] for c in col_r]) 76 | col_r = key_r + col_r 77 | 78 | data = self[idx[:, 1], col_l].data + tbl_r[idx[:, 0], col_r].data 79 | return self.__class__(data, columns=columns) 80 | 81 | def _arg_inner_join(self, index1, tbl_r, index2): 82 | """Perform inner join and return row indices 83 | """ 84 | hash_r = arg_hash(tbl_r[:, index2].data) 85 | return np.array([(s, i) for i, r in enumerate(zip(*self[:, index1].data)) 86 | for s in hash_r[r]]) 87 | 88 | def _arg_outer_join(self, index1, tbl_r, index2): 89 | """Perform outer join and return indices 90 | """ 91 | hash_l = arg_hash(self[:, index1].data) 92 | hash_r = arg_hash(tbl_r[:, index2].data) 93 | 94 | keys = set(hash_l.keys()).union(set(hash_r.keys())) 95 | 96 | def iter_join(h_l, h_r, join_keys): 97 | for join_key in join_keys: 98 | for elem in h_l.get(join_key, [-1]): 99 | for other in h_r.get(join_key, [-1]): 100 | yield (elem, other) 101 | idx = np.array(list(iter_join(hash_l, hash_r, keys))) 102 | return idx[:, [1, 0]] 103 | 104 | def join(self, tbl_r, key, key_r=None, jointype="inner", suffixes=('_l', '_r')): 105 | """dbase join tables with ind column(s) as the keys. 106 | 107 | Performs a database style joins on the two tables, the current instance 108 | and the provided tabel 'tbl_r' on the columns listed in 'key'. 109 | 110 | arguments: 111 | tbl_r (Tabel) : 112 | The right tabel to be joined. 113 | key (string or list) : 114 | Name of the column(s) to be used as the key(s). 115 | key_r (list) : 116 | A list of columnnames of the right tabel matching the left 117 | tabel. Defaults to the list provided in `ind`. 118 | jointype (str) : 119 | One of: `inner`, `left`, `right`, `outer`. If `inner`, returns 120 | the elements common to both tabels. If `outer`, returns the 121 | common elements as well as the elements of the left tabel not in 122 | the right tabel and the elements of the right tabel not in the 123 | left tabel. If `left`, returns the common elements and the 124 | elements of the left tabel not in the right tabel. If `right`, 125 | returns the common elements and the elements of the right tabel 126 | not in the left tabel. 127 | suffixes (tuple) : 128 | Strings to be added to the left and right tabel column names. 129 | 130 | returns: 131 | The joined tabel 132 | 133 | notes: 134 | The order and suffixes of the returned Tabel depend on the jointype. 135 | For all types, all but the key columns are suffixed with the left 136 | and the right suffix respectively. The left Tabel columns come first 137 | followed by the right Tabel columns, with the key column placed 138 | first of its Tabel columns. For `inner` and `left` jointypes the 139 | right key column is left out. for `right` jointype the left key 140 | column is left out. For the `outer` jointype both keys are present 141 | and suffixed. 142 | 143 | Examples: 144 | Join a Tabel into the current Tabel matching on column 'a': 145 | 146 | >>> tbl = Tabel({"a":list(range(4)), "b": ['a', 'b'] *2}) 147 | >>> tbl_b = Tabel({"a":list(range(4)), "c": ['d', 'e'] *2}) 148 | >>> tbl.join(tbl_b, "a") 149 | a | b_l | c_r 150 | -----+-------+------- 151 | 0 | a | d 152 | 1 | b | e 153 | 2 | a | d 154 | 3 | b | e 155 | 4 rows ['>> tbl = Tabel({'a':[10, 20, 30, 40]*3, 'b':["100", "200"]*6, 'c':[100, 200]*6}) 211 | >>> from tabel import first 212 | >>> tbl.group_by(['b', 'a'], [ (np.sum, 'a'), (first, 'c')]) 213 | b | a | a_sum | c_first 214 | -----+-----+---------+----------- 215 | 100 | 10 | 30 | 100 216 | 200 | 20 | 60 | 200 217 | 100 | 30 | 90 | 100 218 | 200 | 40 | 120 | 200 219 | 4 rows [' 0 else None 252 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | About Tabel 2 | ============ 3 | 4 | Lightweight, intuitive and fast data-tables. 5 | 6 | *Tabel* data-tables are tables with columns and column names, rows and row 7 | numbers. Indexing and slicing your data is analogous to numpy array's. The 8 | only real difference is that each column can have its own data type. 9 | 10 | 11 | Design objectives 12 | ----------------- 13 | 14 | I got frustrated with pandas: it's complicated slicing syntax (.loc, .x, 15 | .iloc, .. etc), it's enforced index column and the Series objects I get when I 16 | want a numpy array. With Tabel I created the simplified pandas I need for many 17 | of my data-jobs. Just focussing on simple slicing of multi-datatype tables and 18 | basic table tools. 19 | 20 | * Intuitive simple slicing. 21 | 22 | * Using numpy machinery, for best performance, integration with other tools 23 | and future support. 24 | 25 | * Store data by column numpy arrays (column store). 26 | 27 | * No particular index column, all columns can be used as the index, the choice 28 | is up to the user. 29 | 30 | * Fundamental necessities for sorting, grouping, joining and appending tables. 31 | 32 | 33 | Install 34 | ======== 35 | 36 | pip install tabel 37 | 38 | Quickstart 39 | =========== 40 | 41 | init 42 | ---- 43 | 44 | To setup a Tabel: 45 | 46 | >>> from tabel import Tabel 47 | >>> tbl = Tabel([ ["John", "Joe", "Jane"], 48 | ... [1.82,1.65,2.15], 49 | ... [False,False,True]], columns = ["Name", "Height", "Married"]) 50 | >>> tbl 51 | Name | Height | Married 52 | --------+----------+----------- 53 | John | 1.82 | 0 54 | Joe | 1.65 | 0 55 | Jane | 2.15 | 1 56 | 3 rows ['>> tbl[1:3,[0,2]] 69 | Name | Married 70 | --------+----------- 71 | Joe | 0 72 | Jane | 1 73 | 2 rows ['>> tbl[1:3,'Name'] # doctest: +SKIP 80 | array(['Joe', 'Jane'], 81 | dtype='>> tbl[0,:] 86 | ('John', 1.82, False) 87 | 88 | 3. explicitly one element is requested: 89 | 90 | >>> tbl[0,'Name'] 91 | 'John' 92 | 93 | In general, slicing is intuitive and does not deviate from what would expect 94 | from numpy. With the one addition that columns can be referred to by names as 95 | well as numbers. 96 | 97 | set 98 | ---- 99 | 100 | Setting elements works the same as slicing: 101 | 102 | >>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 103 | >>> tbl[0,"Name"] = "Jos" 104 | >>> tbl 105 | Name | Height | Married 106 | --------+----------+----------- 107 | Jos | 1.82 | 0 108 | Joe | 1.65 | 0 109 | Jane | 2.15 | 1 110 | 3 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 118 | >>> tbl['new'] = [1,2,3] 119 | >>> tbl 120 | Name | Height | Married | new 121 | --------+----------+-----------+------- 122 | John | 1.82 | 0 | 1 123 | Joe | 1.65 | 0 | 2 124 | Jane | 2.15 | 1 | 3 125 | 3 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 130 | >>> tbl['new'] = 13 131 | >>> tbl 132 | Name | Height | Married | new 133 | --------+----------+-----------+------- 134 | John | 1.82 | 0 | 13 135 | Joe | 1.65 | 0 | 13 136 | Jane | 2.15 | 1 | 13 137 | 3 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 148 | >>> tbl += tbl 149 | >>> tbl 150 | Name | Height | Married 151 | --------+----------+----------- 152 | John | 1.82 | 0 153 | Joe | 1.65 | 0 154 | Jane | 2.15 | 1 155 | John | 1.82 | 0 156 | Joe | 1.65 | 0 157 | Jane | 2.15 | 1 158 | 6 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 163 | >>> tbl.row_append({'Height':1.81, 'Name':"Jack", 'Married':True}) 164 | >>> tbl 165 | Name | Height | Married 166 | --------+----------+----------- 167 | John | 1.82 | 0 168 | Joe | 1.65 | 0 169 | Jane | 2.15 | 1 170 | Jack | 1.81 | 1 171 | 4 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 181 | >>> tbl.columns 182 | ['Name', 'Height', 'Married'] 183 | >>> tbl.data # doctest: +SKIP 184 | [array(['John', 'Joe', 'Jane'], 185 | dtype='>> tbl.shape 190 | (3, 3) 191 | >>> len(tbl) 192 | 3 193 | 194 | pandas 195 | ------- 196 | 197 | For for interfacing with the popular datatable framework, going back and forth 198 | is easy: 199 | 200 | >>> import pandas as pd 201 | >>> df = pd.DataFrame({'a':range(3),'b':range(10,13)}) 202 | >>> df 203 | a b 204 | 0 0 10 205 | 1 1 11 206 | 2 2 12 207 | 208 | To make a Tabel from a DataFrame, just supply it to the initialize: 209 | 210 | >>> tbl = Tabel(df) 211 | >>> tbl 212 | a | b 213 | -----+----- 214 | 0 | 10 215 | 1 | 11 216 | 2 | 12 217 | 3 rows ['>> df = pd.DataFrame(tbl.dict) 222 | >>> df 223 | a b 224 | 0 0 10 225 | 1 1 11 226 | 2 2 12 227 | 228 | 229 | Resources & getting help 230 | ========================== 231 | 232 | * See for the full API and more examples the documentation on `RTD `_. 233 | * The repository on `Github `_. 234 | * Installables on `pip `_. 235 | * Questions and answers on `StackOverflow `_, I 236 | will try to monitor for it. 237 | 238 | Stable releases 239 | ================ 240 | * tabel 1.2.3 241 | 242 | * Added __delitem__ feature to delete row(s) or a column. 243 | 244 | * tabel 1.2.2 245 | 246 | * Added argument to save and read methods for csv and gz formats to specify 247 | whether or not to write/read a header with the column names. For reading 248 | header can be left to None for automatic sniffing of the header. Default is 249 | True for both read and save methods. 250 | 251 | * tabel 1.2.1 252 | 253 | * Removed unicode characters from description to fix pip install 254 | `issue `. 255 | 256 | * tabel 1.2.0 257 | 258 | * Fix for numpy 1.15.5 "warnings" 259 | * Fix for outerjoin to raise an error in case of unsupported datatypes 260 | 261 | * tabel 1.1 262 | 263 | * Added join and group_by methods 264 | * September 27, 2018 265 | 266 | * tabel 1.0 267 | 268 | * First release 269 | * September 8, 2018 270 | 271 | 272 | Dependencies 273 | ============ 274 | 275 | * numpy 276 | * tabulate (optional, recommended) 277 | * pandas (optional, for converting back and forth to DataFrames) 278 | 279 | Tested on: 280 | ---------- 281 | 282 | * Python 3.6.4; numpy 1.15.4 283 | * Python 3.6.4; numpy 1.14.3 284 | * Python 2.7.14; numpy 1.14.0 285 | 286 | 287 | Contributing to Tabel 288 | ===================== 289 | Tabel is perfect already, no more contributions needed. Just kidding! 290 | 291 | See the repository for filing issues and proposing enhancements. 292 | 293 | git: 294 | ---- 295 | 296 | * Using master as the development branch 297 | * Every new version is branched of of master (after its finished) into its own 298 | "v1.2.3" named branch. Subsequent version specific fixes can be done in the 299 | version branches. 300 | 301 | 302 | I'm using pytest, pylint, doctest, sphynx and setuptools. 303 | 304 | - git :: 305 | 306 | git checkout master 307 | git pull 308 | 309 | - pytest :: 310 | 311 | cd tabel/test 312 | conda activate py3_6 313 | pytest 314 | conda activate py2_7 315 | pytest 316 | 317 | - pylint :: 318 | 319 | cd tabel/ 320 | ./pylint.sh 321 | 322 | - doctest :: 323 | 324 | cd tabel/docs 325 | make doctest 326 | 327 | - sphynx :: 328 | 329 | cd tabel/docs 330 | make html 331 | 332 | - setuptools/pypi :: 333 | 334 | python setup.py sdist bdist_wheel 335 | twine upload dist/tabel-1.1.0.* 336 | 337 | - git :: 338 | 339 | git add . 340 | git commit -m 341 | git push 342 | git checkout v1.2.3 -b 343 | git push --set-upstream origin v1.2.3 344 | 345 | 346 | 347 | Contributors 348 | ============ 349 | Just me, Bastiaan Bergman [Bastiaan.Bergman@gmail.com]. 350 | 351 | 352 | What's in the name? 353 | =================== 354 | 355 | *Tabel* is Dutch for table (two-dimensional enlisting), `wiktionary 356 | `_. The english word table, as in "dinner 357 | table", translates in Dutch to *tafel*. The Dutch word *tafel* is an old 358 | fashioned word for data-table, mostly used for calculation tables which itself 359 | is old fashioned as well. 360 | 361 | 362 | ToDo 363 | ===== 364 | 365 | * polish error messages and validity checking and add testing for it. 366 | * cache buffers for faster appending: store temp in list and concatenate to 367 | array only once we use another method 368 | * allow for (sparse) numpy arrays as an element 369 | * adjust & limit __repr__ width for very wide Tabels in jupyter cell 370 | * items() and row_items() and keys() and values() method 371 | * pop_column method 372 | * tox - environment testing 373 | * set subsets of tabels with (subsets) of other tabels, seems logic as __setitem__ is 374 | allowed to provide the datatype that should have come from a __getitem__ 375 | * datetime column support 376 | * add disk datalogger 377 | -------------------------------------------------------------------------------- /docs/build/html/_static/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.1 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= 11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/build/html/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Index — tabel v1.0 documentation 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 | 44 | 107 | 108 |
109 | 110 | 111 | 117 | 118 | 119 |
120 | 121 |
122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 |
140 | 141 |
    142 | 143 |
  • Docs »
  • 144 | 145 |
  • Index
  • 146 | 147 | 148 |
  • 149 | 150 | 151 | 152 |
  • 153 | 154 |
155 | 156 | 157 |
158 |
159 |
160 |
161 | 162 | 163 |

Index

164 | 165 |
166 | _ 167 | | A 168 | | D 169 | | F 170 | | G 171 | | J 172 | | M 173 | | R 174 | | S 175 | | T 176 | | V 177 | 178 |
179 |

_

180 | 181 | 187 | 195 |
196 | 197 |

A

198 | 199 | 203 | 207 |
208 | 209 |

D

210 | 211 | 215 | 219 |
220 | 221 |

F

222 | 223 | 227 |
228 | 229 |

G

230 | 231 | 235 |
236 | 237 |

J

238 | 239 | 243 | 247 |
248 | 249 |

M

250 | 251 | 255 |
256 | 257 |

R

258 | 259 | 263 | 269 |
270 | 271 |

S

272 | 273 | 277 | 283 |
284 | 285 |

T

286 | 287 | 293 | 299 |
300 | 301 |

V

302 | 303 | 307 |
308 | 309 | 310 | 311 |
312 | 313 |
314 |
315 | 316 | 317 |
318 | 319 |
320 |

321 | © Copyright 2018, Bastiaan Bergman. 322 | 323 |

324 |
325 | Built with Sphinx using a theme provided by Read the Docs. 326 | 327 |
328 | 329 |
330 |
331 | 332 |
333 | 334 |
335 | 336 | 337 | 338 | 339 | 340 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 364 | 365 | 366 | -------------------------------------------------------------------------------- /docs/build/html/api/module.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | tabel module — tabel v1.0 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 117 | 118 |
119 | 120 | 121 | 127 | 128 | 129 |
130 | 131 |
132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 |
150 | 151 | 169 | 170 | 171 |
172 |
173 |
174 |
175 | 176 |
177 |

tabel module

178 |
179 |

transpose

180 |
181 |
182 | tabel.transpose(datastruct)
183 |

Transpose rows and columns.

184 |

Convenience function. Usually DB connectors return data as a list of 185 | records, Tabel takes and internally stores data as a list of columns (column 186 | store). This function will transpose the list of records into a list of 187 | columns without a priori assuming anything about the datatype of each 188 | individual element.

189 | 190 | 191 | 192 | 193 | 194 | 195 | 197 | 198 | 199 |
Parameters:datastruct (list) – list or tuple containing lists or tuples with the data for each row.
Returns:transposed datastruct, list containing lists with the data for each 196 | column.
200 |
201 | 202 |
203 |
204 | tabel.T(datastruct)
205 |

Convenience alias for tabel.transpose.

206 |
207 | 208 |
209 |
210 |

read_tabel

211 |
212 |
213 | tabel.read_tabel(filename, fmt='auto', header=True)
214 |

Read data from disk

215 |

Read data from disk and return a Tabel object.

216 | 217 | 218 | 219 | 220 | 227 | 228 | 230 | 231 | 232 |
Parameters:
    221 |
  • filename (str) – filename sring, including path and extension.
  • 222 |
  • fmt (str) – format specifier, supports: ‘csv’, ‘npz’, ‘gz’.
  • 223 |
  • header (bool) – whether to expect a header (True) or not (False) or try to sniff 224 | (None), only used for csv and gz
  • 225 |
226 |
Returns:

Tabel object containing the data.

229 |
233 |
234 | 235 |
236 |
237 |

first

238 |
239 |
240 | tabel.first(array)
241 |

Get the first element when doing a tabel.Tabel.group_by.

242 |
243 |
Arguments :
244 |
245 |
array (numpy ndarray) :
246 |
numpy 1D array containing the subset of elements
247 |
248 |
249 |
Returns :
250 |
The first element of ar
251 |
Examples :
252 |
See Tabel.group_by for examples
253 |
254 |
255 | 256 |
257 |
258 | 259 | 260 |
261 | 262 |
263 |
264 | 265 | 273 | 274 | 275 |
276 | 277 |
278 |

279 | © Copyright 2018, Bastiaan Bergman. 280 | 281 |

282 |
283 | Built with Sphinx using a theme provided by Read the Docs. 284 | 285 |
286 | 287 |
288 |
289 | 290 |
291 | 292 |
293 | 294 | 295 | 296 | 297 | 298 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 323 | 324 | -------------------------------------------------------------------------------- /docs/build/html/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | word-wrap: break-word; 56 | overflow-wrap : break-word; 57 | } 58 | 59 | div.sphinxsidebar ul { 60 | list-style: none; 61 | } 62 | 63 | div.sphinxsidebar ul ul, 64 | div.sphinxsidebar ul.want-points { 65 | margin-left: 20px; 66 | list-style: square; 67 | } 68 | 69 | div.sphinxsidebar ul ul { 70 | margin-top: 0; 71 | margin-bottom: 0; 72 | } 73 | 74 | div.sphinxsidebar form { 75 | margin-top: 10px; 76 | } 77 | 78 | div.sphinxsidebar input { 79 | border: 1px solid #98dbcc; 80 | font-family: sans-serif; 81 | font-size: 1em; 82 | } 83 | 84 | div.sphinxsidebar #searchbox input[type="text"] { 85 | float: left; 86 | width: 80%; 87 | padding: 0.25em; 88 | box-sizing: border-box; 89 | } 90 | 91 | div.sphinxsidebar #searchbox input[type="submit"] { 92 | float: left; 93 | width: 20%; 94 | border-left: none; 95 | padding: 0.25em; 96 | box-sizing: border-box; 97 | } 98 | 99 | 100 | img { 101 | border: 0; 102 | max-width: 100%; 103 | } 104 | 105 | /* -- search page ----------------------------------------------------------- */ 106 | 107 | ul.search { 108 | margin: 10px 0 0 20px; 109 | padding: 0; 110 | } 111 | 112 | ul.search li { 113 | padding: 5px 0 5px 20px; 114 | background-image: url(file.png); 115 | background-repeat: no-repeat; 116 | background-position: 0 7px; 117 | } 118 | 119 | ul.search li a { 120 | font-weight: bold; 121 | } 122 | 123 | ul.search li div.context { 124 | color: #888; 125 | margin: 2px 0 0 30px; 126 | text-align: left; 127 | } 128 | 129 | ul.keywordmatches li.goodmatch a { 130 | font-weight: bold; 131 | } 132 | 133 | /* -- index page ------------------------------------------------------------ */ 134 | 135 | table.contentstable { 136 | width: 90%; 137 | margin-left: auto; 138 | margin-right: auto; 139 | } 140 | 141 | table.contentstable p.biglink { 142 | line-height: 150%; 143 | } 144 | 145 | a.biglink { 146 | font-size: 1.3em; 147 | } 148 | 149 | span.linkdescr { 150 | font-style: italic; 151 | padding-top: 5px; 152 | font-size: 90%; 153 | } 154 | 155 | /* -- general index --------------------------------------------------------- */ 156 | 157 | table.indextable { 158 | width: 100%; 159 | } 160 | 161 | table.indextable td { 162 | text-align: left; 163 | vertical-align: top; 164 | } 165 | 166 | table.indextable ul { 167 | margin-top: 0; 168 | margin-bottom: 0; 169 | list-style-type: none; 170 | } 171 | 172 | table.indextable > tbody > tr > td > ul { 173 | padding-left: 0em; 174 | } 175 | 176 | table.indextable tr.pcap { 177 | height: 10px; 178 | } 179 | 180 | table.indextable tr.cap { 181 | margin-top: 10px; 182 | background-color: #f2f2f2; 183 | } 184 | 185 | img.toggler { 186 | margin-right: 3px; 187 | margin-top: 3px; 188 | cursor: pointer; 189 | } 190 | 191 | div.modindex-jumpbox { 192 | border-top: 1px solid #ddd; 193 | border-bottom: 1px solid #ddd; 194 | margin: 1em 0 1em 0; 195 | padding: 0.4em; 196 | } 197 | 198 | div.genindex-jumpbox { 199 | border-top: 1px solid #ddd; 200 | border-bottom: 1px solid #ddd; 201 | margin: 1em 0 1em 0; 202 | padding: 0.4em; 203 | } 204 | 205 | /* -- domain module index --------------------------------------------------- */ 206 | 207 | table.modindextable td { 208 | padding: 2px; 209 | border-collapse: collapse; 210 | } 211 | 212 | /* -- general body styles --------------------------------------------------- */ 213 | 214 | div.body { 215 | min-width: 450px; 216 | max-width: 800px; 217 | } 218 | 219 | div.body p, div.body dd, div.body li, div.body blockquote { 220 | -moz-hyphens: auto; 221 | -ms-hyphens: auto; 222 | -webkit-hyphens: auto; 223 | hyphens: auto; 224 | } 225 | 226 | a.headerlink { 227 | visibility: hidden; 228 | } 229 | 230 | h1:hover > a.headerlink, 231 | h2:hover > a.headerlink, 232 | h3:hover > a.headerlink, 233 | h4:hover > a.headerlink, 234 | h5:hover > a.headerlink, 235 | h6:hover > a.headerlink, 236 | dt:hover > a.headerlink, 237 | caption:hover > a.headerlink, 238 | p.caption:hover > a.headerlink, 239 | div.code-block-caption:hover > a.headerlink { 240 | visibility: visible; 241 | } 242 | 243 | div.body p.caption { 244 | text-align: inherit; 245 | } 246 | 247 | div.body td { 248 | text-align: left; 249 | } 250 | 251 | .first { 252 | margin-top: 0 !important; 253 | } 254 | 255 | p.rubric { 256 | margin-top: 30px; 257 | font-weight: bold; 258 | } 259 | 260 | img.align-left, .figure.align-left, object.align-left { 261 | clear: left; 262 | float: left; 263 | margin-right: 1em; 264 | } 265 | 266 | img.align-right, .figure.align-right, object.align-right { 267 | clear: right; 268 | float: right; 269 | margin-left: 1em; 270 | } 271 | 272 | img.align-center, .figure.align-center, object.align-center { 273 | display: block; 274 | margin-left: auto; 275 | margin-right: auto; 276 | } 277 | 278 | .align-left { 279 | text-align: left; 280 | } 281 | 282 | .align-center { 283 | text-align: center; 284 | } 285 | 286 | .align-right { 287 | text-align: right; 288 | } 289 | 290 | /* -- sidebars -------------------------------------------------------------- */ 291 | 292 | div.sidebar { 293 | margin: 0 0 0.5em 1em; 294 | border: 1px solid #ddb; 295 | padding: 7px 7px 0 7px; 296 | background-color: #ffe; 297 | width: 40%; 298 | float: right; 299 | } 300 | 301 | p.sidebar-title { 302 | font-weight: bold; 303 | } 304 | 305 | /* -- topics ---------------------------------------------------------------- */ 306 | 307 | div.topic { 308 | border: 1px solid #ccc; 309 | padding: 7px 7px 0 7px; 310 | margin: 10px 0 10px 0; 311 | } 312 | 313 | p.topic-title { 314 | font-size: 1.1em; 315 | font-weight: bold; 316 | margin-top: 10px; 317 | } 318 | 319 | /* -- admonitions ----------------------------------------------------------- */ 320 | 321 | div.admonition { 322 | margin-top: 10px; 323 | margin-bottom: 10px; 324 | padding: 7px; 325 | } 326 | 327 | div.admonition dt { 328 | font-weight: bold; 329 | } 330 | 331 | div.admonition dl { 332 | margin-bottom: 0; 333 | } 334 | 335 | p.admonition-title { 336 | margin: 0px 10px 5px 0px; 337 | font-weight: bold; 338 | } 339 | 340 | div.body p.centered { 341 | text-align: center; 342 | margin-top: 25px; 343 | } 344 | 345 | /* -- tables ---------------------------------------------------------------- */ 346 | 347 | table.docutils { 348 | border: 0; 349 | border-collapse: collapse; 350 | } 351 | 352 | table.align-center { 353 | margin-left: auto; 354 | margin-right: auto; 355 | } 356 | 357 | table caption span.caption-number { 358 | font-style: italic; 359 | } 360 | 361 | table caption span.caption-text { 362 | } 363 | 364 | table.docutils td, table.docutils th { 365 | padding: 1px 8px 1px 5px; 366 | border-top: 0; 367 | border-left: 0; 368 | border-right: 0; 369 | border-bottom: 1px solid #aaa; 370 | } 371 | 372 | table.footnote td, table.footnote th { 373 | border: 0 !important; 374 | } 375 | 376 | th { 377 | text-align: left; 378 | padding-right: 5px; 379 | } 380 | 381 | table.citation { 382 | border-left: solid 1px gray; 383 | margin-left: 1px; 384 | } 385 | 386 | table.citation td { 387 | border-bottom: none; 388 | } 389 | 390 | /* -- figures --------------------------------------------------------------- */ 391 | 392 | div.figure { 393 | margin: 0.5em; 394 | padding: 0.5em; 395 | } 396 | 397 | div.figure p.caption { 398 | padding: 0.3em; 399 | } 400 | 401 | div.figure p.caption span.caption-number { 402 | font-style: italic; 403 | } 404 | 405 | div.figure p.caption span.caption-text { 406 | } 407 | 408 | /* -- field list styles ----------------------------------------------------- */ 409 | 410 | table.field-list td, table.field-list th { 411 | border: 0 !important; 412 | } 413 | 414 | .field-list ul { 415 | margin: 0; 416 | padding-left: 1em; 417 | } 418 | 419 | .field-list p { 420 | margin: 0; 421 | } 422 | 423 | .field-name { 424 | -moz-hyphens: manual; 425 | -ms-hyphens: manual; 426 | -webkit-hyphens: manual; 427 | hyphens: manual; 428 | } 429 | 430 | /* -- other body styles ----------------------------------------------------- */ 431 | 432 | ol.arabic { 433 | list-style: decimal; 434 | } 435 | 436 | ol.loweralpha { 437 | list-style: lower-alpha; 438 | } 439 | 440 | ol.upperalpha { 441 | list-style: upper-alpha; 442 | } 443 | 444 | ol.lowerroman { 445 | list-style: lower-roman; 446 | } 447 | 448 | ol.upperroman { 449 | list-style: upper-roman; 450 | } 451 | 452 | dl { 453 | margin-bottom: 15px; 454 | } 455 | 456 | dd p { 457 | margin-top: 0px; 458 | } 459 | 460 | dd ul, dd table { 461 | margin-bottom: 10px; 462 | } 463 | 464 | dd { 465 | margin-top: 3px; 466 | margin-bottom: 10px; 467 | margin-left: 30px; 468 | } 469 | 470 | dt:target, span.highlighted { 471 | background-color: #fbe54e; 472 | } 473 | 474 | rect.highlighted { 475 | fill: #fbe54e; 476 | } 477 | 478 | dl.glossary dt { 479 | font-weight: bold; 480 | font-size: 1.1em; 481 | } 482 | 483 | .optional { 484 | font-size: 1.3em; 485 | } 486 | 487 | .sig-paren { 488 | font-size: larger; 489 | } 490 | 491 | .versionmodified { 492 | font-style: italic; 493 | } 494 | 495 | .system-message { 496 | background-color: #fda; 497 | padding: 5px; 498 | border: 3px solid red; 499 | } 500 | 501 | .footnote:target { 502 | background-color: #ffa; 503 | } 504 | 505 | .line-block { 506 | display: block; 507 | margin-top: 1em; 508 | margin-bottom: 1em; 509 | } 510 | 511 | .line-block .line-block { 512 | margin-top: 0; 513 | margin-bottom: 0; 514 | margin-left: 1.5em; 515 | } 516 | 517 | .guilabel, .menuselection { 518 | font-family: sans-serif; 519 | } 520 | 521 | .accelerator { 522 | text-decoration: underline; 523 | } 524 | 525 | .classifier { 526 | font-style: oblique; 527 | } 528 | 529 | abbr, acronym { 530 | border-bottom: dotted 1px; 531 | cursor: help; 532 | } 533 | 534 | /* -- code displays --------------------------------------------------------- */ 535 | 536 | pre { 537 | overflow: auto; 538 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 539 | } 540 | 541 | span.pre { 542 | -moz-hyphens: none; 543 | -ms-hyphens: none; 544 | -webkit-hyphens: none; 545 | hyphens: none; 546 | } 547 | 548 | td.linenos pre { 549 | padding: 5px 0px; 550 | border: 0; 551 | background-color: transparent; 552 | color: #aaa; 553 | } 554 | 555 | table.highlighttable { 556 | margin-left: 0.5em; 557 | } 558 | 559 | table.highlighttable td { 560 | padding: 0 0.5em 0 0.5em; 561 | } 562 | 563 | div.code-block-caption { 564 | padding: 2px 5px; 565 | font-size: small; 566 | } 567 | 568 | div.code-block-caption code { 569 | background-color: transparent; 570 | } 571 | 572 | div.code-block-caption + div > div.highlight > pre { 573 | margin-top: 0; 574 | } 575 | 576 | div.code-block-caption span.caption-number { 577 | padding: 0.1em 0.3em; 578 | font-style: italic; 579 | } 580 | 581 | div.code-block-caption span.caption-text { 582 | } 583 | 584 | div.literal-block-wrapper { 585 | padding: 1em 1em 0; 586 | } 587 | 588 | div.literal-block-wrapper div.highlight { 589 | margin: 0; 590 | } 591 | 592 | code.descname { 593 | background-color: transparent; 594 | font-weight: bold; 595 | font-size: 1.2em; 596 | } 597 | 598 | code.descclassname { 599 | background-color: transparent; 600 | } 601 | 602 | code.xref, a code { 603 | background-color: transparent; 604 | font-weight: bold; 605 | } 606 | 607 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 608 | background-color: transparent; 609 | } 610 | 611 | .viewcode-link { 612 | float: right; 613 | } 614 | 615 | .viewcode-back { 616 | float: right; 617 | font-family: sans-serif; 618 | } 619 | 620 | div.viewcode-block:target { 621 | margin: -1px -10px; 622 | padding: 0 10px; 623 | } 624 | 625 | /* -- math display ---------------------------------------------------------- */ 626 | 627 | img.math { 628 | vertical-align: middle; 629 | } 630 | 631 | div.body div.math p { 632 | text-align: center; 633 | } 634 | 635 | span.eqno { 636 | float: right; 637 | } 638 | 639 | span.eqno a.headerlink { 640 | position: relative; 641 | left: 0px; 642 | z-index: 1; 643 | } 644 | 645 | div.math:hover a.headerlink { 646 | visibility: visible; 647 | } 648 | 649 | /* -- printout stylesheet --------------------------------------------------- */ 650 | 651 | @media print { 652 | div.document, 653 | div.documentwrapper, 654 | div.bodywrapper { 655 | margin: 0 !important; 656 | width: 100%; 657 | } 658 | 659 | div.sphinxsidebar, 660 | div.related, 661 | div.footer, 662 | #top-link { 663 | display: none; 664 | } 665 | } -------------------------------------------------------------------------------- /tabel.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 2.1 2 | Name: tabel 3 | Version: 1.2.3 4 | Summary: Lightweight, intuitive and fast data-tables. 5 | Home-page: https://github.com/BastiaanBergman/tabel 6 | Author: Bastiaan Bergman 7 | Author-email: Bastiaan.Bergman@gmail.com 8 | License: MIT 9 | Project-URL: Documentation, https://tabel.readthedocs.io/en/stable/ 10 | Project-URL: Source Code, https://github.com/BastiaanBergman/tabel 11 | Description: About Tabel 12 | ============ 13 | 14 | Lightweight, intuitive and fast data-tables. 15 | 16 | *Tabel* data-tables are tables with columns and column names, rows and row 17 | numbers. Indexing and slicing your data is analogous to numpy array's. The 18 | only real difference is that each column can have its own data type. 19 | 20 | 21 | Design objectives 22 | ----------------- 23 | 24 | I got frustrated with pandas: it's complicated slicing syntax (.loc, .x, 25 | .iloc, .. etc), it's enforced index column and the Series objects I get when I 26 | want a numpy array. With Tabel I created the simplified pandas I need for many 27 | of my data-jobs. Just focussing on simple slicing of multi-datatype tables and 28 | basic table tools. 29 | 30 | * Intuitive simple slicing. 31 | 32 | * Using numpy machinery, for best performance, integration with other tools 33 | and future support. 34 | 35 | * Store data by column numpy arrays (column store). 36 | 37 | * No particular index column, all columns can be used as the index, the choice 38 | is up to the user. 39 | 40 | * Fundamental necessities for sorting, grouping, joining and appending tables. 41 | 42 | 43 | Install 44 | ======== 45 | 46 | pip install tabel 47 | 48 | Quickstart 49 | =========== 50 | 51 | init 52 | ---- 53 | 54 | To setup a Tabel: 55 | 56 | >>> from tabel import Tabel 57 | >>> tbl = Tabel([ ["John", "Joe", "Jane"], 58 | ... [1.82,1.65,2.15], 59 | ... [False,False,True]], columns = ["Name", "Height", "Married"]) 60 | >>> tbl 61 | Name | Height | Married 62 | --------+----------+----------- 63 | John | 1.82 | 0 64 | Joe | 1.65 | 0 65 | Jane | 2.15 | 1 66 | 3 rows ['>> tbl[1:3,[0,2]] 79 | Name | Married 80 | --------+----------- 81 | Joe | 0 82 | Jane | 1 83 | 2 rows ['>> tbl[1:3,'Name'] # doctest: +SKIP 90 | array(['Joe', 'Jane'], 91 | dtype='>> tbl[0,:] 96 | ('John', 1.82, False) 97 | 98 | 3. explicitly one element is requested: 99 | 100 | >>> tbl[0,'Name'] 101 | 'John' 102 | 103 | In general, slicing is intuitive and does not deviate from what would expect 104 | from numpy. With the one addition that columns can be referred to by names as 105 | well as numbers. 106 | 107 | set 108 | ---- 109 | 110 | Setting elements works the same as slicing: 111 | 112 | >>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 113 | >>> tbl[0,"Name"] = "Jos" 114 | >>> tbl 115 | Name | Height | Married 116 | --------+----------+----------- 117 | Jos | 1.82 | 0 118 | Joe | 1.65 | 0 119 | Jane | 2.15 | 1 120 | 3 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 128 | >>> tbl['new'] = [1,2,3] 129 | >>> tbl 130 | Name | Height | Married | new 131 | --------+----------+-----------+------- 132 | John | 1.82 | 0 | 1 133 | Joe | 1.65 | 0 | 2 134 | Jane | 2.15 | 1 | 3 135 | 3 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 140 | >>> tbl['new'] = 13 141 | >>> tbl 142 | Name | Height | Married | new 143 | --------+----------+-----------+------- 144 | John | 1.82 | 0 | 13 145 | Joe | 1.65 | 0 | 13 146 | Jane | 2.15 | 1 | 13 147 | 3 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 158 | >>> tbl += tbl 159 | >>> tbl 160 | Name | Height | Married 161 | --------+----------+----------- 162 | John | 1.82 | 0 163 | Joe | 1.65 | 0 164 | Jane | 2.15 | 1 165 | John | 1.82 | 0 166 | Joe | 1.65 | 0 167 | Jane | 2.15 | 1 168 | 6 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 173 | >>> tbl.row_append({'Height':1.81, 'Name':"Jack", 'Married':True}) 174 | >>> tbl 175 | Name | Height | Married 176 | --------+----------+----------- 177 | John | 1.82 | 0 178 | Joe | 1.65 | 0 179 | Jane | 2.15 | 1 180 | Jack | 1.81 | 1 181 | 4 rows ['>> tbl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}) 191 | >>> tbl.columns 192 | ['Name', 'Height', 'Married'] 193 | >>> tbl.data # doctest: +SKIP 194 | [array(['John', 'Joe', 'Jane'], 195 | dtype='>> tbl.shape 200 | (3, 3) 201 | >>> len(tbl) 202 | 3 203 | 204 | pandas 205 | ------- 206 | 207 | For for interfacing with the popular datatable framework, going back and forth 208 | is easy: 209 | 210 | >>> import pandas as pd 211 | >>> df = pd.DataFrame({'a':range(3),'b':range(10,13)}) 212 | >>> df 213 | a b 214 | 0 0 10 215 | 1 1 11 216 | 2 2 12 217 | 218 | To make a Tabel from a DataFrame, just supply it to the initialize: 219 | 220 | >>> tbl = Tabel(df) 221 | >>> tbl 222 | a | b 223 | -----+----- 224 | 0 | 10 225 | 1 | 11 226 | 2 | 12 227 | 3 rows ['>> df = pd.DataFrame(tbl.dict) 232 | >>> df 233 | a b 234 | 0 0 10 235 | 1 1 11 236 | 2 2 12 237 | 238 | 239 | Resources & getting help 240 | ========================== 241 | 242 | * See for the full API and more examples the documentation on `RTD `_. 243 | * The repository on `Github `_. 244 | * Installables on `pip `_. 245 | * Questions and answers on `StackOverflow `_, I 246 | will try to monitor for it. 247 | 248 | Stable releases 249 | ================ 250 | * tabel 1.2.3 251 | 252 | * Added __delitem__ feature to delete row(s) or a column. 253 | 254 | * tabel 1.2.2 255 | 256 | * Added argument to save and read methods for csv and gz formats to specify 257 | whether or not to write/read a header with the column names. For reading 258 | header can be left to None for automatic sniffing of the header. Default is 259 | True for both read and save methods. 260 | 261 | * tabel 1.2.1 262 | 263 | * Removed unicode characters from description to fix pip install 264 | `issue `. 265 | 266 | * tabel 1.2.0 267 | 268 | * Fix for numpy 1.15.5 "warnings" 269 | * Fix for outerjoin to raise an error in case of unsupported datatypes 270 | 271 | * tabel 1.1 272 | 273 | * Added join and group_by methods 274 | * September 27, 2018 275 | 276 | * tabel 1.0 277 | 278 | * First release 279 | * September 8, 2018 280 | 281 | 282 | Dependencies 283 | ============ 284 | 285 | * numpy 286 | * tabulate (optional, recommended) 287 | * pandas (optional, for converting back and forth to DataFrames) 288 | 289 | Tested on: 290 | ---------- 291 | 292 | * Python 3.6.4; numpy 1.15.4 293 | * Python 3.6.4; numpy 1.14.3 294 | * Python 2.7.14; numpy 1.14.0 295 | 296 | 297 | Contributing to Tabel 298 | ===================== 299 | Tabel is perfect already, no more contributions needed. Just kidding! 300 | 301 | See the repository for filing issues and proposing enhancements. 302 | 303 | I'm using pytest, pylint, doctest, sphynx and setuptools. 304 | 305 | - pytest :: 306 | 307 | cd tabel/test 308 | conda activate py3_6 309 | pytest 310 | conda activate py2_7 311 | pytest 312 | 313 | - pylint :: 314 | 315 | cd tabel/ 316 | ./pylint.sh 317 | 318 | - doctest :: 319 | 320 | cd tabel/docs 321 | make doctest 322 | 323 | - sphynx :: 324 | 325 | cd tabel/docs 326 | make html 327 | 328 | - setuptools/pypi :: 329 | 330 | python setup.py sdist bdist_wheel 331 | twine upload dist/tabel-1.1.0.* 332 | 333 | 334 | Contributors 335 | ============ 336 | Just me, Bastiaan Bergman [Bastiaan.Bergman@gmail.com]. 337 | 338 | 339 | What's in the name? 340 | =================== 341 | 342 | *Tabel* is Dutch for table (two-dimensional enlisting), `wiktionary 343 | `_. The english word table, as in "dinner 344 | table", translates in Dutch to *tafel*. The Dutch word *tafel* is an old 345 | fashioned word for data-table, mostly used for calculation tables which itself 346 | is old fashioned as well. 347 | 348 | 349 | ToDo 350 | ===== 351 | 352 | * polish error messages and validity checking and add testing for it. 353 | * cache buffers for faster appending: store temp in list and concatenate to 354 | array only once we use another method 355 | * allow for (sparse) numpy arrays as an element 356 | * adjust & limit __repr__ width for very wide Tabels in jupyter cell 357 | * items() and row_items() and keys() and values() method 358 | * pop_column method 359 | * tox - environment testing 360 | * set subsets of tabels with (subsets) of other tabels, seems logic as __setitem__ is 361 | allowed to provide the datatype that should have come from a __getitem__ 362 | * datetime column support 363 | * add disk datalogger 364 | 365 | Keywords: data table 366 | Platform: UNKNOWN 367 | Classifier: Programming Language :: Python :: 3 368 | Classifier: Programming Language :: Python :: 3.6 369 | Classifier: Programming Language :: Python :: 2 370 | Classifier: Programming Language :: Python :: 2.7 371 | Classifier: License :: OSI Approved :: MIT License 372 | Classifier: Operating System :: OS Independent 373 | Requires-Python: >=2.6, >=3.0 374 | Description-Content-Type: text/x-rst 375 | -------------------------------------------------------------------------------- /test/test_tabel.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | local_path = os.path.abspath(os.path.join(os.getcwd(), "../")) 4 | sys.path.insert(0,local_path) 5 | 6 | from tabel import Tabel, read_tabel, T, first 7 | import os 8 | import pytest 9 | import numpy as np 10 | from itertools import product 11 | from copy import copy, deepcopy 12 | import pandas as pd 13 | 14 | def naneq(a, b): 15 | """ Test wether a and b are equal, counting both nan as being equal. 16 | """ 17 | try: 18 | return np.all(np.isnan(a) == np.isnan(b)) or np.all(a == b) 19 | except TypeError as e: 20 | return np.all(a == b) 21 | 22 | @pytest.fixture 23 | def tbls(): 24 | tbls = [Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]}), 25 | Tabel([ np.array(["John", "Joe", "Jane"]),np.array([1.82,1.65,2.15]),np.array([False,False,True])], columns = ["Name", "Height", "Married"]), 26 | Tabel([ ["John", "Joe", "Jane"],[1.82,1.65,2.15],[False,False,True]], columns = ["Name", "Height", "Married"]), 27 | Tabel(), 28 | Tabel([1,2,3]), 29 | Tabel({'a':range(10),'b':range(10)}), 30 | Tabel({'a':range(10),'b':list(map(str, range(10)))}), 31 | Tabel([range(10),range(10),range(10)]), 32 | Tabel(np.array([np.arange(10),np.arange(10,20)])), 33 | Tabel({'a':12,'b':13}), 34 | Tabel(pd.DataFrame({'a':[12]*6, 'b':np.arange(6), 'c':range(6)})), 35 | Tabel({'a':[3,4,5], 'b':1}), 36 | Tabel({'a':1, 'b':[3,4,5]}), 37 | Tabel({'aa':[1,1,1], 'b':[3,4,5]}), 38 | ] 39 | return tbls 40 | 41 | 42 | class TestTabelInit(object): 43 | def test_tabel_init(self, tbls): 44 | for tbl in tbls: 45 | assert tbl.valid 46 | 47 | 48 | class TestAppend(object): 49 | def test_append_tabel(self, tbls): 50 | for tbl in tbls: 51 | length = len(tbl) 52 | tbl += tbl 53 | assert tbl.valid 54 | assert len(tbl) == 2 * length 55 | 56 | def test_append_column(self, tbls): 57 | for tbl in tbls: 58 | width = tbl.shape[1] 59 | ln = len(tbl) 60 | tbl["n1"] = 12 61 | tbl["n2"] = "Foo" 62 | tbl["n3"] = np.arange(len(tbl)) 63 | tbl["n4"] = [12]*len(tbl) 64 | tbl["n5"] = ["Bar"]*len(tbl) 65 | assert tbl.valid 66 | assert tbl.shape[1] == width + 5 67 | if ln > 0: 68 | assert len(tbl) == ln 69 | 70 | def test_append_combinations(self): 71 | first_tbl = [Tabel(), Tabel({'a':2,'b':3}), Tabel({'a':"ff",'b':"ffr"})] 72 | seccond_tbl = [Tabel({'a':22,'b':13}), pd.DataFrame({'a':[22],'b':[13]}), 73 | Tabel({'a':"ff",'b':"ffr"}), 74 | pd.DataFrame({'a':["jdw"],'b':["okdw"]}), 75 | ] 76 | for ftbl, stbl in product(first_tbl, seccond_tbl): 77 | ftbl = deepcopy(ftbl) 78 | fl = len(ftbl) 79 | ftbl.append(stbl) 80 | assert ftbl.valid 81 | assert len(ftbl) == fl + 1 82 | 83 | def test_row_append_combinations(self): 84 | first_tbl = [Tabel(), Tabel({'a':2,'b':3}), Tabel({'a':"ff",'b':"ffr"})] 85 | seccond_tbl = [{'a':22,'b':13}, [22,33], (44,55), np.array([33,33]), 86 | {'a':"ded",'b':"fr"}, ["frd","werf"], 87 | ("efds","dew"), np.array(["frde","frtg"])] 88 | for ftbl, stbl in product(first_tbl, seccond_tbl): 89 | ftbl = deepcopy(ftbl) 90 | fl = len(ftbl) 91 | ftbl.row_append(stbl) 92 | assert ftbl.valid 93 | assert len(ftbl) == fl + 1 94 | 95 | 96 | class TestSlice(object): 97 | def test_slice_type(self, tbls): 98 | for tbl in tbls: 99 | if len(tbl) > 0: 100 | assert type(tbl[0]) == tuple 101 | assert type(tbl[:,0]) == np.ndarray 102 | assert type(tbl[:,:]) == Tabel 103 | assert type(tbl[0,0]) == type(tbl.data[0][0]) 104 | assert type(tbl[[0],[0]]) == Tabel 105 | (r,c) = tbl.shape 106 | assert type(tbl[np.array([True]*r),np.array([True]*c)]) == Tabel 107 | assert type(tbl[list(range(r)),list(range(c))]) == Tabel 108 | assert type(tbl[:,:]) == Tabel 109 | 110 | def test_slice_columns(self, tbls): 111 | for tbl in tbls: 112 | if tbl: 113 | assert np.all(tbl[:,0] == tbl.data[0]) 114 | assert np.all(tbl[:,tbl.columns[0]] == tbl.data[0]) 115 | 116 | def test_slice_rows(self, tbls): 117 | for tbl in tbls: 118 | if tbl: 119 | assert np.all(tbl[0][0] == tbl.data[0][0]) 120 | 121 | def test_slice_boolean(self, tbls): 122 | for tbl in tbls: 123 | if tbl.shape[0] > 0 & tbl.shape[1] > 0: 124 | ind = tbl[:,0] == 0 125 | ind = ind if isinstance(ind, np.ndarray) else np.array([ind]) 126 | assert type(tbl[ind,:]) == Tabel 127 | 128 | def test_slice_permiseable(self, tbls): 129 | row_it = [slice(0,2,None), [0,1], np.array([True,False,True]), 0, np.array([0,1]), 130 | np.array([False, True, False]), slice(0,3,2)] 131 | col_it = row_it + [["Name", "Height"], "Name", ["Height", "Name"]] 132 | keys = list(product(row_it, col_it)) 133 | for tbl in tbls[0:3]: 134 | for key in keys: 135 | _ = tbl[key] 136 | 137 | 138 | class TestSetter(object): 139 | def test_set_individual_elm(self, tbls): 140 | for tbl in tbls[0:3]: 141 | tbl[0,0] = "Bas" 142 | tbl[1,1] = 12 143 | tbl[2,1] = True 144 | 145 | def test_set_column(self, tbls): 146 | for tbl in tbls[:3]: 147 | i = tbl.columns.index("Name") 148 | tbl[0:2,i] = np.array(["Bas", "Jack"]) 149 | tbl[0:2,"Name"] = ["Bas", "Jack"] 150 | tbl[[0], "Name"] = ["Bas"] 151 | length = len(tbl) 152 | tbl["Name"] = "Blanc" 153 | assert np.all(tbl["Name"] == np.array(length*["Blanc"]).astype(tbl["Name"].dtype)) 154 | tbl[[False, True, False], 1] = [13] 155 | tbl["Name"] = ["Noone"] * length 156 | tbl[:, "Name"] = ["Noone"] * length 157 | 158 | def test_set_row(self): 159 | tbl = Tabel({"a":list(range(2,6)), "b": ['1','2'] *2, "c":[1.1,2.2]*2}) 160 | tbl[0,:] = (12, "12", 12.12) 161 | tbl[1,['a','b']] = [12, "12"] 162 | tbl[2] = (13, "13", 13.13) 163 | tbl[3, np.array([True, False, True])] = (14, 14.14) 164 | 165 | def test_add_column(self): 166 | tbl = Tabel({"a":list(range(2,6)), "b": ['1','2'] *2, "c":[1.1,2.2]*2}) 167 | tbl["d"] = np.array([True]*len(tbl)) 168 | tbl["e"] = 100 169 | tbl["f"] = "Blanc" 170 | assert len(tbl.columns) == 6 171 | assert np.all([len(c)==len(tbl) for c in tbl.data]) 172 | 173 | def test_replace_column(self): 174 | tbl = Tabel({"a":list(range(2,6)), "b": ['1','2'] *2, "c":[1.1,2.2]*2}) 175 | tbl[:,"a"] = np.array([1.4,2.4]*2) 176 | assert tbl[0,'a'] == 1 177 | tbl["a"] = np.array([1.1,2.2]*2) 178 | assert tbl['a'].dtype == np.float 179 | tbl[:,"b"] = np.arange(4) 180 | assert tbl[0, "b"] == "0" 181 | tbl["b"] = np.arange(4) 182 | assert tbl[0, "b"] == 0 183 | tbl[:,"c"] = np.arange(4) 184 | assert tbl["c"].dtype == np.float 185 | tbl["c"] = np.arange(4) 186 | assert tbl["c"].dtype == np.int 187 | 188 | 189 | class TestSaveNRead(object): 190 | def test_save_n_read(self, tbls, tmpdir): 191 | for header in [True, False]: 192 | for fmt in ['csv', 'gz', 'npz']: 193 | for tbl in tbls: 194 | if len(tbl) > 0: 195 | fn = os.path.join(str(tmpdir), "test."+fmt) 196 | tbl.save(fn, header=header) 197 | tbl_r = read_tabel(fn, header=header) 198 | assert (set(tbl_r.columns) == set(tbl.columns)) or (not header), (tbl, tbl_r) 199 | assert len(tbl_r) == len(tbl), (tbl, tbl_r) 200 | assert tbl_r.valid, (tbl, tbl_r) 201 | 202 | if not tbl_r.columns[0].isdigit() and len(tbl)>2: 203 | # header sniffer should work 204 | tbl_r = read_tabel(fn, header=None) 205 | assert set(tbl_r.columns) == set(tbl.columns), (tbl, tbl_r) 206 | assert len(tbl_r) == len(tbl), (tbl, tbl_r) 207 | 208 | class TestGroupBy(object): 209 | def test_group_by(self): 210 | tbl = Tabel({'a':[10,20,30, 40]*3, 'b':["100","200"]*6, 'c':[100,200]*6}) 211 | tbl_g = tbl.group_by(['b','a'], [(np.sum, 'a'), (first, 'c')]) 212 | idx = np.argsort(tbl_g['a_sum']) 213 | assert np.all(tbl_g[idx, 'a_sum'] == np.array([30, 60, 90, 120])) 214 | assert np.all(tbl['a'] == [10,20,30, 40]*3) 215 | assert np.all(tbl_g[idx, 'c_first'] == np.array([100, 200, 100, 200])) 216 | tbl_g = tbl.group_by(['b','a'], []) 217 | idx = np.argsort(tbl_g['a']) 218 | assert np.all(tbl_g[idx, 'a'] == [10,20,30,40]) 219 | 220 | 221 | class TestShapeNLen(object): 222 | def test_shape_n_len(self, tbls): 223 | for tbl in tbls: 224 | assert len(tbl) == tbl.shape[0] 225 | 226 | def test_shape(self, tbls): 227 | for tbl in tbls: 228 | assert len(tbl.columns) == tbl.shape[1] 229 | assert len(tbl.data) == tbl.shape[1] 230 | 231 | def test_len(self, tbls): 232 | for tbl in tbls: 233 | for c in tbl.columns: 234 | assert len(tbl[c]) == tbl.shape[0] 235 | 236 | 237 | class TestTranspose(object): 238 | def test_transpose(self, tbls): 239 | for tbl in tbls: 240 | if len(tbl) == 0: 241 | continue 242 | lrec = [tbl[i] for i in range(len(tbl))] 243 | tbl_n = Tabel(T(lrec)) 244 | for i,column in enumerate(tbl.columns): 245 | assert np.all(tbl[column] == tbl_n[str(i)]) 246 | lrec = [list(tbl[i]) for i in range(len(tbl))] 247 | tbl_n = Tabel(T(lrec)) 248 | for i,column in enumerate(tbl.columns): 249 | assert np.all(tbl[column] == tbl_n[str(i)]) 250 | 251 | 252 | class TestJoin(object): 253 | def test_inner_int_join(self): 254 | tbl = Tabel({"a":list(range(4)), "b": ['a','b'] *2}) 255 | tbl_b = Tabel({"a":list(range(2,6)), "c": ['d','e'] *2}) 256 | tbl_j = tbl.join(tbl_b, "a") 257 | assert "c_r" in tbl_j.columns 258 | assert tbl_j[0] == (2,'a','d') 259 | assert len(tbl_j) == 2 260 | assert np.all(tbl[0] == (0,'a')) 261 | 262 | def test_inner_str_join(self): 263 | tbl = Tabel({"a":list(map(str, range(4))), "b": ['a','b'] *2}) 264 | tbl_b = Tabel({"a":list(map(str, range(4))), "c": ['d','e'] *2}) 265 | tbl_j = tbl.join(tbl_b, "a", jointype="inner") 266 | assert "c_r" in tbl_j.columns 267 | assert tbl_j[0] == ('0','a','d') 268 | assert len(tbl_j) == 4 269 | assert np.all(tbl[0] == ('0','a')) 270 | 271 | def test_outer_join(self): 272 | tbl = Tabel({"a":list(range(4)), "b": ['a','b'] *2}) 273 | tbl_b = Tabel({"a":list(range(2,6)), "c": [1,2] *2, "d":[1.1,2.2]*2}) 274 | tbl_j = tbl.join(tbl_b, "a", jointype='outer') 275 | naneq(tbl_j[tbl_j['a_l']==0,'c_r'], Tabel.join_fill_value['integer']) 276 | naneq(tbl_j[tbl_j['a_l']==0, 'd_r'], Tabel.join_fill_value['float']) 277 | naneq(tbl_j[tbl_j['a_r']==4, 'b_l'], Tabel.join_fill_value['string']) 278 | assert "c_r" in tbl_j.columns 279 | assert len(tbl_j) == 6 280 | 281 | 282 | class TestSort(object): 283 | def test_sort(self): 284 | tbl = Tabel({'aa':['b','g','d'], 'b':list(range(3))}) 285 | tbl.sort('aa') 286 | assert tbl[0] == ('b',0) 287 | assert tbl[1] == ('d',2) 288 | tbl.sort(['aa', 'b']) 289 | assert tbl[1] == ('g',1) 290 | 291 | 292 | class TestDTypeProperties(object): 293 | def test_dtype_properties(self): 294 | tbl = Tabel({"a":list(range(2,6)), "c": [u'1',u'2'] *2, "d":[1.1,2.2]*2}) 295 | assert tbl.dtype == np.dtype([('a', '