Package: tabl
About TabelLightweight, intuitive and fast data-tables.Tabeldata-tables are tables with columns and column names, rows and row
numbers. Indexing and slicing your data is analogous to numpy array’s. The
only real difference is that each column can have its own data type.Design objectivesI got frustrated with pandas: it’s complicated slicing syntax (.loc, .x,
.iloc, .. etc), it’s enforced index column and the Series objects I get when I
want a numpy array. With Tabel I created the simplified pandas I need for many
of my data-jobs. Just focussing on simple slicing of multi-datatype tables and
basic table tools.Intuitive simple slicing.Using numpy machinery, for best performance, integration with other tools
and future support.Store data by column numpy arrays (column store).No particular index column, all columns can be used as the index, the choice
is up to the user.Fundamental necessities for sorting, grouping, joining and appending tables.Installpip install tabelQuickstartinitTo setup a Tabel:>>> from tabel import Tabel
>>> tabl = Tabel([ ["John", "Joe", "Jane"],
...                [1.82,1.65,2.15],
...                [False,False,True]], columns = ["Name", "Height", "Married"])
>>> tabl
 Name   |   Height |   Married
--------+----------+-----------
 John   |     1.82 |         0
 Joe    |     1.65 |         0
 Jane   |     2.15 |         1
3 rows ['<U4', '<f8', '|b1']Alternatively, Tabels can be setup from dictionaries, numpy arrays, pandas
DataFrames, or no data at all. Database connectors usually return data as a list
of records, the module provides a convenience function to transpose this into a
list of columns.sliceSlicing can be done the numpy way, always returning Tabel objects:>>> tabl[1:3,[0,2]]
 Name   |   Married
--------+-----------
 Joe    |         0
 Jane   |         1
2 rows ['<U4', '|b1']Slices will always return a Tabel except in three distinct cases, when:explicitly one column is requested, a numpy array is returned:>>> tabl[1:3,'Name']       # doctest: +SKIP
array(['Joe', 'Jane'],
      dtype='<U4')explicitly one row is requested, a tuple is returned:>>> tabl[0,:]
('John', 1.82, False)explicitly one element is requested:>>> tabl[0,'Name']
'John'In general, slicing is intuitive and does not deviate from what would expect
from numpy. With the one addition that columns can be referred to by names as
well as numbers.setSetting elements works the same as slicing:>>> tabl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]})
>>> tabl[0,"Name"] = "Jos"
>>> tabl
 Name   |   Height |   Married
--------+----------+-----------
 Jos    |     1.82 |         0
 Joe    |     1.65 |         0
 Jane   |     2.15 |         1
3 rows ['<U4', '<f8', '|b1']The datatype that the value is expected to have, is the same as the datatype a
slice would result into.Adding columns, works the same as setting elements, just give it a new name:>>> tabl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]})
>>> tabl['new'] = [1,2,3]
>>> tabl
 Name   |   Height |   Married |   new
--------+----------+-----------+-------
 John   |     1.82 |         0 |     1
 Joe    |     1.65 |         0 |     2
 Jane   |     2.15 |         1 |     3
3 rows ['<U4', '<f8', '|b1', '<i8']Or set the whole column to the same value:>>> tabl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]})
>>> tabl['new'] = 13
>>> tabl
 Name   |   Height |   Married |   new
--------+----------+-----------+-------
 John   |     1.82 |         0 |    13
 Joe    |     1.65 |         0 |    13
 Jane   |     2.15 |         1 |    13
3 rows ['<U4', '<f8', '|b1', '<i8']Just like numpy, slices are not actual copies of the data, rather they are
references.append Tabel and rowTabels can be appended with other Tabels:>>> tabl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]})
>>> tabl += tabl
>>> tabl
 Name   |   Height |   Married
--------+----------+-----------
 John   |     1.82 |         0
 Joe    |     1.65 |         0
 Jane   |     2.15 |         1
 John   |     1.82 |         0
 Joe    |     1.65 |         0
 Jane   |     2.15 |         1
6 rows ['<U4', '<f8', '|b1']Or append rows as dictionary:>>> tabl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]})
>>> tabl.row_append({'Height':1.81, 'Name':"Jack", 'Married':True})
>>> tabl
 Name   |   Height |   Married
--------+----------+-----------
 John   |     1.82 |         0
 Joe    |     1.65 |         0
 Jane   |     2.15 |         1
 Jack   |     1.81 |         1
4 rows ['<U4', '<f8', '|b1']instance propertiesYour data is simply stored as a list of numpy arrays and can be accessed or
manipulated like that (just don’t make a mess):>>> tabl = Tabel({'Name' : ["John", "Joe", "Jane"], 'Height' : [1.82,1.65,2.15], 'Married': [False,False,True]})
>>> tabl.columns
['Name', 'Height', 'Married']
>>> tabl.data        # doctest: +SKIP
[array(['John', 'Joe', 'Jane'],
      dtype='<U4'), array([ 1.82,  1.65,  2.15]), array([False, False,  True], dtype=bool)]Further the basic means to asses the size of your data:>>> tabl.shape
(3, 3)
>>> len(tabl)
3pandasFor for interfacing with the popular datatable framework, going back and forth
is easy:>>> import pandas as pd
>>> df = pd.DataFrame({'a':range(3),'b':range(10,13)})
>>> df
   a   b
0  0  10
1  1  11
2  2  12To make a Tabel from a DataFrame, just supply it to the initialize:>>> tabl = Tabel(df)
>>> tabl
   a |   b
-----+-----
   0 |  10
   1 |  11
   2 |  12
3 rows ['<i8', '<i8']The dict property of Tabel provides a way to make a DataFrame from a Tabel:>>> df = pd.DataFrame(tabl.dict)
>>> df
   a   b
0  0  10
1  1  11
2  2  12Resources & getting helpSee for the full API and more examples the documentation onRTD.The repository onGithub.Installables onpip.Questions and answers onStackOverflow, I
will try to monitor for it.Stable releasestabel 1.2.3Added __delitem__ feature to delete row(s) or a column.tabel 1.2.2Added argument to save and read methods for csv and gz formats to specify
whether or not to write/read a header with the column names. For reading
header can be left to None for automatic sniffing of the header. Default is
True for both read and save methods.tabel 1.2.1Removed unicode characters from description to fix pip installissue <https://github.com/BastiaanBergman/tabel/issues/6#issue-440282452>.tabel 1.2.0Fix for numpy 1.15.5 “warnings”Fix for outerjoin to raise an error in case of unsupported datatypestabel 1.1Added join and group_by methodsSeptember 27, 2018tabel 1.0First releaseSeptember 8, 2018Dependenciesnumpytabulate (optional, recommended)pandas (optional, for converting back and forth to DataFrames)Tested on:Python 3.6.4;  numpy 1.15.4Python 3.6.4;  numpy 1.14.3Python 2.7.14; numpy 1.14.0Contributing to TabelTabel is perfect already, no more contributions needed. Just kidding!See the repository for filing issues and proposing enhancements.git:Using master as the development branchEvery new version is branched of of master (after its finished) into its own
“v1.2.3” named branch. Subsequent version specific fixes can be done in the
version branches.I’m using pytest, pylint, doctest, sphynx and setuptools.gitgit checkout master
git pullpytestcd tabel/test
conda activate py3_6
pytest
conda activate py2_7
pytestpylintcd tabel/
./pylint.shdoctestcd tabel/docs
make doctestsphynxcd tabel/docs
make htmlsetuptools/pypipython setup.py sdist bdist_wheel
twine upload dist/tabel-1.1.0.*gitgit add .
git commit -m
git push
git checkout v1.2.3 -b
git push --set-upstream origin v1.2.3ContributorsJust me, Bastiaan Bergman [Bastiaan.Bergman@gmail.com].What’s in the name?Tabelis Dutch for table (two-dimensional enlisting),wiktionary. The english word table, as in “dinner
table”, translates in Dutch totafel. The Dutch wordtafelis an old
fashioned word for data-table, mostly used for calculation tables which itself
is old fashioned as well.ToDopolish error messages and validity checking and add testing for it.cache buffers for faster appending: store temp in list and concatenate to
array only once we use another methodallow for (sparse) numpy arrays as an elementadjust & limit __repr__ width for very wide Tabels in jupyter cellitems() and row_items() and keys() and values() methodpop_column methodtox - environment testingset subsets of tabels with (subsets) of other tabels, seems logic as __setitem__ is
allowed to provide the datatype that should have come from a __getitem__datetime column supportadd disk datalogger