tablelab 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tablelab-0.5.0/.gitignore +42 -0
- tablelab-0.5.0/CHANGELOG.md +64 -0
- tablelab-0.5.0/LICENSE +21 -0
- tablelab-0.5.0/PKG-INFO +465 -0
- tablelab-0.5.0/README.md +420 -0
- tablelab-0.5.0/RELEASING.md +67 -0
- tablelab-0.5.0/examples/data/sensor_log.csv +201 -0
- tablelab-0.5.0/examples/data/signals.csv +120 -0
- tablelab-0.5.0/examples/data/test_table1.csv +4 -0
- tablelab-0.5.0/examples/data/test_table2.csv +4 -0
- tablelab-0.5.0/examples/tablelab_queries.ipynb +153 -0
- tablelab-0.5.0/pyproject.toml +60 -0
- tablelab-0.5.0/src/tablelab/__init__.py +72 -0
- tablelab-0.5.0/src/tablelab/__main__.py +64 -0
- tablelab-0.5.0/src/tablelab/app.py +431 -0
- tablelab-0.5.0/src/tablelab/charts.py +242 -0
- tablelab-0.5.0/src/tablelab/code_export.py +545 -0
- tablelab-0.5.0/src/tablelab/column_inspector.py +303 -0
- tablelab-0.5.0/src/tablelab/figures.py +101 -0
- tablelab-0.5.0/src/tablelab/file_readers.py +129 -0
- tablelab-0.5.0/src/tablelab/filepicker.py +195 -0
- tablelab-0.5.0/src/tablelab/helpers/__init__.py +50 -0
- tablelab-0.5.0/src/tablelab/helpers/data.py +30 -0
- tablelab-0.5.0/src/tablelab/helpers/plotting.py +31 -0
- tablelab-0.5.0/src/tablelab/helpers/widgets.py +5 -0
- tablelab-0.5.0/src/tablelab/missing_values.py +97 -0
- tablelab-0.5.0/src/tablelab/paged_preview.py +152 -0
- tablelab-0.5.0/src/tablelab/pipeline.py +202 -0
- tablelab-0.5.0/src/tablelab/query_app.py +1343 -0
- tablelab-0.5.0/src/tablelab/query_expressions.py +91 -0
- tablelab-0.5.0/src/tablelab/table.py +128 -0
- tablelab-0.5.0/tests/test_code_export.py +274 -0
- tablelab-0.5.0/tests/test_code_usability.py +83 -0
- tablelab-0.5.0/tests/test_column_relationship.py +235 -0
- tablelab-0.5.0/tests/test_group_alias.py +63 -0
- tablelab-0.5.0/tests/test_group_key_order.py +62 -0
- tablelab-0.5.0/tests/test_missing_values.py +133 -0
- tablelab-0.5.0/tests/test_pipeline.py +308 -0
- tablelab-0.5.0/tests/test_query_app.py +769 -0
- tablelab-0.5.0/tests/test_query_extensions.py +183 -0
- tablelab-0.5.0/tests/test_release.py +38 -0
- tablelab-0.5.0/tests/test_smoke.py +362 -0
- tablelab-0.5.0/tests/test_table_urls.py +105 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Virtual environments
|
|
2
|
+
venv/
|
|
3
|
+
.venv/
|
|
4
|
+
env/
|
|
5
|
+
|
|
6
|
+
# Python bytecode
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.py[cod]
|
|
9
|
+
|
|
10
|
+
# Jupyter
|
|
11
|
+
.ipynb_checkpoints/
|
|
12
|
+
*/.ipynb_checkpoints/
|
|
13
|
+
|
|
14
|
+
# IDE
|
|
15
|
+
.idea/
|
|
16
|
+
.vscode/
|
|
17
|
+
|
|
18
|
+
# macOS
|
|
19
|
+
.DS_Store
|
|
20
|
+
|
|
21
|
+
# R
|
|
22
|
+
.Rhistory
|
|
23
|
+
|
|
24
|
+
# Generated run outputs (timestamped fit results are reproducible; keep them local)
|
|
25
|
+
outputs/
|
|
26
|
+
|
|
27
|
+
# Packaging
|
|
28
|
+
build/
|
|
29
|
+
dist/
|
|
30
|
+
*.egg-info/
|
|
31
|
+
.uv-cache/
|
|
32
|
+
|
|
33
|
+
# Test cache
|
|
34
|
+
.pytest_cache/
|
|
35
|
+
|
|
36
|
+
# Kept locally, not part of the published package
|
|
37
|
+
archive/
|
|
38
|
+
artifacts/
|
|
39
|
+
INVENTORY.md
|
|
40
|
+
requirements.txt
|
|
41
|
+
.Rhistory
|
|
42
|
+
article/
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.5.0 — 2026-10-12
|
|
4
|
+
|
|
5
|
+
- Join preview colours and origin legend for left, right, and shared-key columns.
|
|
6
|
+
- Preserve available join keys across input refreshes; switch to Select after saving a Join.
|
|
7
|
+
- Input and distinct row counts beside Select sorting controls.
|
|
8
|
+
- Category encoding with visible mappings for inspection and comparison plots.
|
|
9
|
+
- Coloured pipeline/preview buttons, clearer intermediate-preview label, and inline fill-value control.
|
|
10
|
+
- Small CSV examples demonstrating all four join types.
|
|
11
|
+
|
|
12
|
+
## 0.4.0 — 2026-10-10
|
|
13
|
+
|
|
14
|
+
- Independent inspector row range, initially rows 1–100, with Show all for statistics and plots.
|
|
15
|
+
|
|
16
|
+
- Remove the separate chart GUI notebook; use `examples/tablelab_queries.ipynb` as the main example.
|
|
17
|
+
|
|
18
|
+
- MySQL 8+, PostgreSQL, SQLite 3.39+, and DuckDB SQL exports for query settings and pipelines,
|
|
19
|
+
with source table mappings and explicit errors for unsupported dialect operations.
|
|
20
|
+
|
|
21
|
+
## 0.3.0 — 2026-10-10
|
|
22
|
+
|
|
23
|
+
- Separate query GUI with Select, Join, Filter, Group & summarise, and Missing values.
|
|
24
|
+
- Editable query pipelines with saved steps, previews, and per-source session state.
|
|
25
|
+
- Standalone Pandas, PySpark, and Spark SQL exports, including file loading,
|
|
26
|
+
execution guidance, and a Copy code button with a manual-copy fallback.
|
|
27
|
+
- Ordered grouping keys and optional summary aliases.
|
|
28
|
+
- Integrated column comparison: scatter plots or two curves against sample positions,
|
|
29
|
+
sharing the inspector's chart area and preserving source/query data.
|
|
30
|
+
- Direct HTTP/HTTPS table downloads, verified HTTPS using certifi, and clearer load errors.
|
|
31
|
+
- Separate source and column inspection panels, paged previews, source CSV saving,
|
|
32
|
+
and consistent replacement of outputs in Jupyter and VS Code.
|
|
33
|
+
- Public `query_main` / `QueryApp` imports, CLI `--version`, portable release examples,
|
|
34
|
+
and a documented version/build process. The existing `main` / `TableApp` API is retained.
|
|
35
|
+
|
|
36
|
+
## 0.2.0
|
|
37
|
+
|
|
38
|
+
- **Browse...** — a file dialog over the folders the kernel can see, so a local
|
|
39
|
+
table is read where it sits instead of being copied through the browser.
|
|
40
|
+
Clicking a folder walks into it; **Upload** is still there for the remote case.
|
|
41
|
+
- **A chart menu** — the run chart is joined by a sorted run chart, a histogram,
|
|
42
|
+
a box plot and an ECDF, all reachable as functions or through `draw(kind, ...)`.
|
|
43
|
+
- **Pan and zoom** — the app activates the ipympl backend when it is installed,
|
|
44
|
+
which puts a toolbar under the chart. `main(zoom=False)` leaves the notebook's
|
|
45
|
+
backend alone.
|
|
46
|
+
- **Grid lines** — a checkbox, applied to the figure on screen rather than by
|
|
47
|
+
redrawing, so turning it on does not reset the zoom.
|
|
48
|
+
- **Summary statistics** — quartiles, spread and skew for the series on screen,
|
|
49
|
+
folded out below the chart. `summary_stats(values)` from a cell.
|
|
50
|
+
- `--chart` and `--grid` on the command line.
|
|
51
|
+
|
|
52
|
+
## 0.1.0
|
|
53
|
+
|
|
54
|
+
First release.
|
|
55
|
+
|
|
56
|
+
- Widget app: load a table by path or upload, inspect it, chart it.
|
|
57
|
+
- Two chart modes - a **column** down the rows, or a **row** across the columns
|
|
58
|
+
for tables where each row is a signal.
|
|
59
|
+
- Label detection by column name, or by position for headerless tables. The row
|
|
60
|
+
slider filters by label, and the row's label titles the chart.
|
|
61
|
+
- Header sniffing on delimited files, so a headerless table does not lose its
|
|
62
|
+
first row to pandas' column names.
|
|
63
|
+
- Run chart with a median (or mean) reference line, direct-labelled.
|
|
64
|
+
- `python -m tablelab` command line front end over the same functions.
|
tablelab-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Reza Berangi
|
|
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.
|
tablelab-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: tablelab
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Notebook GUI for table inspection, query pipelines, charts, and Pandas/PySpark/Spark SQL code generation
|
|
5
|
+
Project-URL: Homepage, https://github.com/rberangi/tablelab
|
|
6
|
+
Project-URL: Source, https://github.com/rberangi/tablelab
|
|
7
|
+
Project-URL: Issues, https://github.com/rberangi/tablelab/issues
|
|
8
|
+
Author-email: Reza Berangi <rberangi@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: data inspection,ipywidgets,jupyter,pandas,pyspark,query,sql,table,visualization
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Framework :: Jupyter
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Requires-Dist: certifi>=2024.2.2
|
|
19
|
+
Requires-Dist: ipywidgets>=8.0
|
|
20
|
+
Requires-Dist: matplotlib>=3.9
|
|
21
|
+
Requires-Dist: numpy>=1.23
|
|
22
|
+
Requires-Dist: pandas>=1.5
|
|
23
|
+
Requires-Dist: sqlglot>=25
|
|
24
|
+
Provides-Extra: all
|
|
25
|
+
Requires-Dist: ipympl>=0.9; extra == 'all'
|
|
26
|
+
Requires-Dist: openpyxl; extra == 'all'
|
|
27
|
+
Requires-Dist: pyarrow; extra == 'all'
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: duckdb>=1; extra == 'dev'
|
|
30
|
+
Requires-Dist: jupyterlab; extra == 'dev'
|
|
31
|
+
Requires-Dist: nbconvert; extra == 'dev'
|
|
32
|
+
Requires-Dist: nbformat; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
34
|
+
Requires-Dist: sqlglot>=25; extra == 'dev'
|
|
35
|
+
Provides-Extra: excel
|
|
36
|
+
Requires-Dist: openpyxl; extra == 'excel'
|
|
37
|
+
Provides-Extra: parquet
|
|
38
|
+
Requires-Dist: pyarrow; extra == 'parquet'
|
|
39
|
+
Provides-Extra: release
|
|
40
|
+
Requires-Dist: build>=1.2; extra == 'release'
|
|
41
|
+
Requires-Dist: twine>=5; extra == 'release'
|
|
42
|
+
Provides-Extra: zoom
|
|
43
|
+
Requires-Dist: ipympl>=0.9; extra == 'zoom'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# tablelab
|
|
47
|
+
|
|
48
|
+
Current release: **0.5.0**.
|
|
49
|
+
|
|
50
|
+
TableLab is a notebook GUI for exploring and transforming tables. Select columns,
|
|
51
|
+
filter rows, join tables, create grouped summaries, handle missing values, and
|
|
52
|
+
build saved query pipelines. Inspect columns with statistics and plots, then
|
|
53
|
+
export pandas, PySpark, or SQL code from the same settings.
|
|
54
|
+
|
|
55
|
+
Start with `examples/tablelab_queries.ipynb` or launch `query_main()` below.
|
|
56
|
+
The separate `main()` API remains available for column and row chart inspection.
|
|
57
|
+
|
|
58
|
+
## New in 0.5.0
|
|
59
|
+
|
|
60
|
+
- Join previews colour left columns blue, right columns orange, and shared keys
|
|
61
|
+
purple, with a visible legend. Key selections survive pipeline refreshes when
|
|
62
|
+
their columns still exist.
|
|
63
|
+
- Saving a Join switches to Select with all result columns selected, preventing
|
|
64
|
+
the next preview from repeating the same join accidentally.
|
|
65
|
+
- Select shows **Input rows** and **Distinct rows** beside Ascending. Distinct
|
|
66
|
+
counts use the selected columns and calculations, before Limit and Offset.
|
|
67
|
+
- **Inspect a column → Encode categories** displays a category-to-code mapping
|
|
68
|
+
and supports individual plots, scatter comparisons, and two curves versus
|
|
69
|
+
samples. Codes follow first appearance in the full source and remain stable
|
|
70
|
+
when changing the inspection range. Missing values stay missing; source data
|
|
71
|
+
is unchanged. Codes are labels, so their distances and averages have no
|
|
72
|
+
statistical interpretation.
|
|
73
|
+
- Green **Run pipeline** and blue preview buttons distinguish saved-pipeline
|
|
74
|
+
execution from the current settings. Fill value appears beside Action.
|
|
75
|
+
- `examples/data/test_table1.csv` and `test_table2.csv` demonstrate all four joins;
|
|
76
|
+
select `order_id` as the key in both tables.
|
|
77
|
+
|
|
78
|
+
## Preview and save steps
|
|
79
|
+
|
|
80
|
+
| Control | Behaviour |
|
|
81
|
+
|---|---|
|
|
82
|
+
| **Apply and preview result** | Apply the current tab settings to the current pipeline input, without saving a step. |
|
|
83
|
+
| **Add step** | Save the current operation and use its result as the input for the next operation. |
|
|
84
|
+
| **Preview up to this step** | Run saved steps from the beginning through the highlighted step. |
|
|
85
|
+
| **Run pipeline** | Run all saved steps, ignoring unsaved tab settings. |
|
|
86
|
+
| **Edit step** | Restore a saved step's tab and settings; use Save changes or Cancel edit afterward. |
|
|
87
|
+
|
|
88
|
+
Selecting an entry in the step list highlights it; use **Edit step** to restore
|
|
89
|
+
its settings. Previews do not change the original source tables. After installing
|
|
90
|
+
an update, restart the notebook kernel and rerun the launcher to replace an old GUI.
|
|
91
|
+
|
|
92
|
+
## Install
|
|
93
|
+
|
|
94
|
+
Install the local 0.5.0 release from the project folder:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
python -m pip install dist/tablelab-0.5.0-py3-none-any.whl
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
In a notebook, use `%pip install /full/path/to/tablelab-0.5.0-py3-none-any.whl`
|
|
101
|
+
in the selected kernel, then restart it. Launch the query GUI with:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
import tablelab
|
|
105
|
+
from tablelab import query_main
|
|
106
|
+
|
|
107
|
+
print(tablelab.__version__)
|
|
108
|
+
app = query_main()
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`from tablelab import main` continues to launch the column/row chart GUI.
|
|
112
|
+
For installation from the package index, use:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
pip install tablelab
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Optional readers and the pan/zoom toolbar are extras:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pip install "tablelab[all]"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
SQL code generation dependencies, including `sqlglot`, are installed automatically
|
|
125
|
+
with TableLab. In Jupyter, use `%pip` so installation targets the active notebook
|
|
126
|
+
kernel. To install the current source checkout and its dependencies, run:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
%pip install -e /full/path/to/tablelab
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Restart the kernel after installation and relaunch TableLab. Existing release
|
|
133
|
+
wheels keep the dependencies recorded when they were built; rebuild the wheel
|
|
134
|
+
after changing `pyproject.toml` before distributing the updated package.
|
|
135
|
+
|
|
136
|
+
**Inspect a column** has independent Start row and End row controls (inclusive,
|
|
137
|
+
starting at 1). It initially inspects the first 100 rows; **Show all** selects the
|
|
138
|
+
full source. Statistics, categorical counts, and comparison plots use this range.
|
|
139
|
+
This reduces inspection work; the full source table remains loaded in memory.
|
|
140
|
+
|
|
141
|
+
| Extra | Adds |
|
|
142
|
+
|---|---|
|
|
143
|
+
| `excel` | `.xlsx`, `.xls` |
|
|
144
|
+
| `parquet` | `.parquet`, `.feather`, `.arrow` |
|
|
145
|
+
| `zoom` | pan/zoom toolbar on the run chart |
|
|
146
|
+
| `all` | all of the above |
|
|
147
|
+
|
|
148
|
+
## After installing
|
|
149
|
+
|
|
150
|
+
tablelab is a widget app, so it runs inside a notebook — not in a plain Python
|
|
151
|
+
script.
|
|
152
|
+
|
|
153
|
+
**1. Open a notebook** in the same Python environment you installed into:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
pip install jupyterlab # skip if you already have Jupyter
|
|
157
|
+
jupyter lab
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
VS Code works too: create a `.ipynb` file and select that Python as the kernel.
|
|
161
|
+
|
|
162
|
+
**2. Start the app** in a notebook cell:
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
from tablelab import main
|
|
166
|
+
|
|
167
|
+
app = main() # load a file from the UI
|
|
168
|
+
# app = main("data/ecg.csv") # or open on a file
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`app.df` is the active DataFrame, so you can keep working on it in the next cell.
|
|
172
|
+
Each load adds a table to the **table:** menu. Switch between loaded tables
|
|
173
|
+
without reading them again, or use **Remove table** to remove the selected one.
|
|
174
|
+
Adding the same disk path again selects its existing table. Uploads are kept
|
|
175
|
+
separately, even when their filenames match. Switching tables resets the column,
|
|
176
|
+
label filter, and row selection. Loaded tables stay in memory for the app session.
|
|
177
|
+
|
|
178
|
+
For the shortest route, open `examples/tablelab_queries.ipynb` and run its GUI
|
|
179
|
+
cell. The release example is a portable notebook with no saved outputs.
|
|
180
|
+
|
|
181
|
+
For joins and queries, use the same `examples/tablelab_queries.ipynb`.
|
|
182
|
+
Its GUI supports left/inner/right/outer joins (including multiple matching keys),
|
|
183
|
+
column filters, and grouped counts, sums, means, medians, minima, and maxima.
|
|
184
|
+
The **Select** tab beside **Join** provides SQL-like column selection,
|
|
185
|
+
**Distinct rows**, **Order by** (ascending or descending), **Limit**, and **Offset**.
|
|
186
|
+
All columns are selected initially; limit 0 keeps all remaining rows. Sorting
|
|
187
|
+
columns must be included in the output. Use **Add step** to combine filtering,
|
|
188
|
+
joining, selection, grouping, and missing-value handling in a pipeline.
|
|
189
|
+
**Show code** includes file loading and the matching pandas selection.
|
|
190
|
+
In **Select**, click **Add column alias** to rename an output column. Click
|
|
191
|
+
**Add calculated column** to enter a new name and an expression such as
|
|
192
|
+
`price * quantity` or `total * (1 - 0.1)`. Calculations run in row order, can
|
|
193
|
+
reference earlier calculated columns, and are included in the output. Use
|
|
194
|
+
`col('unit price')` for a column name with spaces, or `col(0)` for an integer
|
|
195
|
+
column name. Expressions support numbers, parentheses, `+`, `-`, `*`, `/`,
|
|
196
|
+
`//`, and `%`. Choose sorting columns by their original or calculated names;
|
|
197
|
+
aliases are applied after sorting. Duplicate output names are rejected.
|
|
198
|
+
|
|
199
|
+
In **Filter**, the original condition is number 1. Use **Add condition** for
|
|
200
|
+
more rows and choose **All (AND)**, **Any (OR)**, or **Custom grouping**.
|
|
201
|
+
Only **Custom grouping** enables the **Grouping** field, which requires an
|
|
202
|
+
expression such as `1 AND (2 OR 3)`. All/Any ignores the inactive field. Removing a condition
|
|
203
|
+
renumbers the remaining rows, so update explicit grouping if necessary.
|
|
204
|
+
All three additions are included in **Show code**. Source tables are
|
|
205
|
+
unchanged; changing editor input resets draft aliases, calculations, and extra
|
|
206
|
+
conditions. Saved pipeline steps keep their settings.
|
|
207
|
+
|
|
208
|
+
The **Missing values** tab previews missing counts and percentages for selected
|
|
209
|
+
columns. Choose **Remove rows** to drop rows where any or all selected values
|
|
210
|
+
are missing, **Fill with a fixed value**, or **Fill with median**. These actions
|
|
211
|
+
preserve the source and are included in **Show code**. Median filling
|
|
212
|
+
requires numeric columns and leaves entirely missing columns unchanged; nullable
|
|
213
|
+
integer columns are promoted to nullable floating point when the median is
|
|
214
|
+
fractional. Fixed values are converted to each affected column's type (use
|
|
215
|
+
`true`/`false` for Boolean columns); blank strings are ordinary values. Only
|
|
216
|
+
selected columns are cleaned. Use **Add step** to continue querying the cleaned
|
|
217
|
+
result, or **Add as new table** to keep a separate table.
|
|
218
|
+
|
|
219
|
+
The **Query pipeline** panel stores operations in order. Configure a tab, then
|
|
220
|
+
click **Add step**: its output becomes the input for the next operation, without
|
|
221
|
+
creating an intermediate table. **Apply and preview result** previews the current
|
|
222
|
+
unsaved settings; **Run pipeline** previews all saved steps. Select a step and
|
|
223
|
+
use **Preview selected step** to inspect that stage. **Edit step** loads its saved
|
|
224
|
+
settings against the preceding stage; **Save changes** recomputes later steps,
|
|
225
|
+
and **Cancel edit** restores the saved pipeline. You can move steps up/down,
|
|
226
|
+
remove them, or clear the pipeline. If an upstream change removes a column used
|
|
227
|
+
later, the affected steps are marked **needs update** with a specific error;
|
|
228
|
+
edit the first failing step to choose available columns.
|
|
229
|
+
|
|
230
|
+
**Show pipeline code** generates code in the selected output language for saved steps,
|
|
231
|
+
including the original source and right-table reads. **Show code** includes
|
|
232
|
+
the saved prefix and the current draft (while editing, through the edited step).
|
|
233
|
+
Pipelines are kept separately for each loaded source for the current app session.
|
|
234
|
+
Saved joins retain their right input if it is removed from the table menu.
|
|
235
|
+
**View source table**, **Inspect a column**, and **Save source as CSV** continue
|
|
236
|
+
to use the original source. The operation controls and `app.df` use the current
|
|
237
|
+
pipeline input. **Add as new table** keeps whichever result is being previewed.
|
|
238
|
+
|
|
239
|
+
The shared **Column** selector chooses the column for filtering and grouped
|
|
240
|
+
summaries. The selected column is shaded in the result preview; grouped summaries
|
|
241
|
+
shade the calculated column. Numeric summaries require a numeric column.
|
|
242
|
+
Preview the result, then add it as a new table to chain operations. A **Remove table**
|
|
243
|
+
button sits beside the source selector. To export the selected source, click **Save source as CSV**, browse to a
|
|
244
|
+
destination folder, enter a filename, and click **Save**. This saves all rows
|
|
245
|
+
and columns as UTF-8 CSV without the DataFrame index, regardless of the preview
|
|
246
|
+
range. Paths refer to the notebook kernel’s filesystem; existing files are kept
|
|
247
|
+
and require a different destination name. The notebook includes optional Customers
|
|
248
|
+
and Orders sample tables. Source tables stay unchanged;
|
|
249
|
+
the full previewed result is available as `app.result`.
|
|
250
|
+
Expand **View source table** to browse source rows. Open the separate
|
|
251
|
+
**Inspect a column** section to inspect individual columns with the chart GUI's numeric charts, data type selector, summary statistics, and
|
|
252
|
+
categorical value counts. Column inspection uses the full source table and does
|
|
253
|
+
not change the query settings or result. The standalone chart notebook also
|
|
254
|
+
supports inspecting rows as signals.
|
|
255
|
+
The **Source table** panel lets you browse the entire selected source using
|
|
256
|
+
Start row and End row fields that show the current page boundaries and update
|
|
257
|
+
with Previous/Next. Page size is End row − Start row + 1, initially up to 100.
|
|
258
|
+
Editing either field resizes the page; Previous/Next retains that size, including
|
|
259
|
+
after a shorter final page. It shares the loaded table and renders only the
|
|
260
|
+
current page; collapsed panels render no table
|
|
261
|
+
HTML. The selected source range only controls the preview, not the query input.
|
|
262
|
+
After applying a query, use the Start row and End row fields to choose which
|
|
263
|
+
result rows to preview, or use Previous/Next to page through the result.
|
|
264
|
+
Paging retains the selected page size, including after a shorter final page.
|
|
265
|
+
Positions start at 1 and include
|
|
266
|
+
both endpoints. The initial preview shows up to 100 rows so large results appear
|
|
267
|
+
quickly. Column headers stay visible at the top while scrolling source and result
|
|
268
|
+
previews. Change the row range to view other rows; adding the result as a table
|
|
269
|
+
retains every result row, regardless of the preview range.
|
|
270
|
+
|
|
271
|
+
The implementation helpers are also available under `tablelab.helpers` for a
|
|
272
|
+
notebook that needs to build on the supplied GUI:
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from tablelab.helpers import load_table, run_chart, summary_stats
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## The UI
|
|
279
|
+
|
|
280
|
+
| control | what it does |
|
|
281
|
+
|---|---|
|
|
282
|
+
| **Browse...** | a file dialog over the folders the kernel can see |
|
|
283
|
+
| path box + **Add table** | the same, by typing, when the path is already known |
|
|
284
|
+
| **table:** | switch between loaded tables |
|
|
285
|
+
| **Remove table** | remove the selected table |
|
|
286
|
+
| **Upload** | for a file on your machine when the kernel is on another one |
|
|
287
|
+
| **Column / Row** | which direction the series runs in |
|
|
288
|
+
| **column:** | the menu of all the table's columns; the data type box sits after it |
|
|
289
|
+
| **Data type** | automatically selects Numeric or Categorical; numeric columns can be viewed as categories |
|
|
290
|
+
| drawing tabs | run chart, sorted run chart, histogram, box plot or ECDF; numeric data only |
|
|
291
|
+
| **centre:** | the dashed reference line — median, mean, or none |
|
|
292
|
+
| **grid lines** | vertical grid lines as well as the horizontal ones |
|
|
293
|
+
|
|
294
|
+
Above the chart is a toolbar that pans and zooms. **First rows** folds out above
|
|
295
|
+
the column and row selections; **Summary statistics** folds out below the chart.
|
|
296
|
+
The data type selector automatically chooses Numeric or Categorical when you
|
|
297
|
+
select a column, and shows its pandas dtype. For numeric columns such as class
|
|
298
|
+
codes, choose Categorical to see value counts, or switch back to Numeric for
|
|
299
|
+
drawings. This changes the view without changing the underlying data. Selecting
|
|
300
|
+
another column or table restores automatic detection. Other data uses the
|
|
301
|
+
categorical view; the tooltip shows its detected type.
|
|
302
|
+
Numeric data offers drawing tabs for Run chart, Sorted run chart, Histogram,
|
|
303
|
+
Box plot, and ECDF. Other data shows value counts and hides the drawing controls.
|
|
304
|
+
|
|
305
|
+
The toolbar comes from `ipympl` (`pip install "tablelab[zoom]"`). Without it the
|
|
306
|
+
chart is a static image and everything else still works. Because switching
|
|
307
|
+
matplotlib backends affects the whole notebook, `main(zoom=False)` leaves it
|
|
308
|
+
alone.
|
|
309
|
+
|
|
310
|
+
Ticking **grid lines** applies the grid to the figure on screen rather than
|
|
311
|
+
redrawing it, so it does not throw away a zoom you are in the middle of.
|
|
312
|
+
|
|
313
|
+
### Browse or Upload
|
|
314
|
+
|
|
315
|
+
**Browse...** lists the filesystem the *kernel* can see, which is the right one
|
|
316
|
+
for local work and for a notebook on a server — the file is read where it
|
|
317
|
+
already is, at any size. **Upload** copies a file through the browser instead,
|
|
318
|
+
for when the kernel is somewhere the file is not. The dialog is built from
|
|
319
|
+
widgets rather than a native file chooser on purpose: a native one opens on the
|
|
320
|
+
machine running the kernel, which over SSH or in a container is not the machine
|
|
321
|
+
you are looking at.
|
|
322
|
+
|
|
323
|
+
## Label detection
|
|
324
|
+
|
|
325
|
+
tablelab looks for the label column in two passes:
|
|
326
|
+
|
|
327
|
+
1. A column named `label`, `class`, `target`, `y`, `activity` or `diagnosis`
|
|
328
|
+
(case-insensitive).
|
|
329
|
+
2. Failing that, and only for a **headerless** table: the last column, if it has
|
|
330
|
+
at most 20 distinct values. Headerless tables name their columns by position,
|
|
331
|
+
so nothing else can say which one is the label.
|
|
332
|
+
|
|
333
|
+
`describe(df)` prints which column it picked and the class counts, so the guess
|
|
334
|
+
is always visible rather than silent. In the CLI, `--label-col` overrides it.
|
|
335
|
+
|
|
336
|
+
Headerless files are detected too: if every field in the first row parses as a
|
|
337
|
+
number, that row is data, and pandas is told not to take it for column names.
|
|
338
|
+
Without this, ECG5000 quietly loses its first beat.
|
|
339
|
+
|
|
340
|
+
## Without widgets
|
|
341
|
+
|
|
342
|
+
The reading, the label detection and the chart are plain functions — the app is
|
|
343
|
+
only a shell around them:
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
from tablelab import load_table, find_label_column, describe, summary_stats
|
|
347
|
+
from tablelab import run_chart, sorted_run_chart, histogram, box_plot, ecdf, draw
|
|
348
|
+
|
|
349
|
+
df = load_table("data/ecg.csv")
|
|
350
|
+
print(describe(df)) # 4998 rows x 141 columns, label -> ...
|
|
351
|
+
run_chart(df.iloc[0, :-1], title="beat 0")
|
|
352
|
+
histogram(df["rr"], ylabel="rr", grid=True)
|
|
353
|
+
draw("ecdf", df["rr"], ylabel="rr") # by the key the chart menu uses
|
|
354
|
+
summary_stats(df["rr"]) # quartiles, spread, skew, as a table
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
There is a command line front end for the same thing:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
python -m tablelab data/ecg.csv --list
|
|
361
|
+
python -m tablelab data/ecg.csv --row 0
|
|
362
|
+
python -m tablelab data/ecg.csv --col temperature --chart histogram --grid
|
|
363
|
+
python -m tablelab data/ecg.csv --col temperature --out chart.png
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## The charts
|
|
367
|
+
|
|
368
|
+
Five views of the one series, all with the same furniture:
|
|
369
|
+
|
|
370
|
+
| chart | what it answers |
|
|
371
|
+
|---|---|
|
|
372
|
+
| Run chart | how the values move in order — drift, steps, cycles |
|
|
373
|
+
| Sorted run chart | the range, the gaps, how far the extremes sit from the body |
|
|
374
|
+
| Histogram | where the values sit, order thrown away |
|
|
375
|
+
| Box plot | median, quartiles, whiskers and the points outside them |
|
|
376
|
+
| ECDF | the proportion at or below each value, with nothing binned away |
|
|
377
|
+
|
|
378
|
+
One series, so one hue and no legend — the title names the series, and the
|
|
379
|
+
median line is labelled where it sits. `centre="mean"` switches the reference
|
|
380
|
+
line; `centre=None` removes it; a box plot draws its own median and ignores it.
|
|
381
|
+
Markers appear only when there are at most 60 points, past which they stop
|
|
382
|
+
carrying information and only thicken the line.
|
|
383
|
+
|
|
384
|
+
`grid` is three-valued rather than a flag: `"y"` is the run chart's own grid and
|
|
385
|
+
the default, `True` adds the vertical lines the app's checkbox asks for, and
|
|
386
|
+
`False` takes both away.
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
MIT
|
|
391
|
+
|
|
392
|
+
Choose **Code output: Pandas / PySpark / Spark SQL / MySQL / PostgreSQL / SQLite / DuckDB**, then **Show code** for the
|
|
393
|
+
saved prefix plus current settings, or **Show pipeline code** for saved steps only.
|
|
394
|
+
Generated code appears in the preview window with instructions for where to run it.
|
|
395
|
+
Use **Copy code** to copy the displayed code. If your notebook blocks clipboard
|
|
396
|
+
access or JavaScript output, select the code and copy it manually. Changing the
|
|
397
|
+
output language or query settings clears old code so it cannot be copied by mistake.
|
|
398
|
+
PySpark exports include a Spark
|
|
399
|
+
session, file reads with schemas, transformations, and result display. SQL exports
|
|
400
|
+
include temporary input views and a query with named steps. Both cover Select,
|
|
401
|
+
Join, Filter, Group & summarise, and Missing values.
|
|
402
|
+
|
|
403
|
+
Database SQL exports target **MySQL 8+**, **PostgreSQL**, **SQLite 3.39+**, or
|
|
404
|
+
**DuckDB**. Import each listed source file into its named `tablelab_input_0`,
|
|
405
|
+
`tablelab_input_1`, etc. table before running the generated query in a SQL editor.
|
|
406
|
+
Keep the original column names and types, and load missing values as SQL NULL.
|
|
407
|
+
These exports include projections, aliases, calculations, DISTINCT, sorting,
|
|
408
|
+
pagination, joins, filters, grouped summaries, and missing-value handling, composed
|
|
409
|
+
as named query steps (CTEs). They do not connect to a database or import files.
|
|
410
|
+
MySQL full outer joins and median operations in MySQL, PostgreSQL, and SQLite
|
|
411
|
+
currently report an export error; use DuckDB or Spark SQL for those settings.
|
|
412
|
+
Database sorting/collation, arithmetic, and timestamps can differ from pandas.
|
|
413
|
+
|
|
414
|
+
Previews still run locally with pandas; exporting code does not run Spark or
|
|
415
|
+
require PySpark to be installed in TableLab. Run exports in a **Spark 3.5+**
|
|
416
|
+
environment and review file paths, schema types, CSV null tokens, and timezone
|
|
417
|
+
settings. CSV/TSV, Parquet, and line-delimited JSON have native readers. Other
|
|
418
|
+
formats and in-memory tables include instructions to export a CSV first. Spark
|
|
419
|
+
has no pandas index or guaranteed row order; use unique sorting keys when
|
|
420
|
+
LIMIT/OFFSET must be reproducible. Inputs normalize numeric NaN to NULL and joins
|
|
421
|
+
use null-safe equality. Arithmetic, overflow, and division by zero follow Spark
|
|
422
|
+
settings. Unsupported mixed/nested or timedelta columns report an export error.
|
|
423
|
+
|
|
424
|
+
The file path field also accepts direct **HTTP/HTTPS table download URLs**, such as
|
|
425
|
+
`https://raw.githubusercontent.com/mwaskom/seaborn-data/master/tips.csv`.
|
|
426
|
+
Paste the URL and click **Add table**. With an empty field, **Add table** opens the
|
|
427
|
+
file picker. Web page links are rejected with a message requesting a direct file
|
|
428
|
+
link. URL data is downloaded into memory, like a local source. Pandas exports
|
|
429
|
+
retain the URL; Spark exports instruct you to download the file first.
|
|
430
|
+
|
|
431
|
+
HTTPS loading supplements Python's default trusted certificates with the
|
|
432
|
+
`certifi` bundle while retaining certificate and hostname verification. If an
|
|
433
|
+
older notebook environment reports `CERTIFICATE_VERIFY_FAILED`, run
|
|
434
|
+
`%pip install --upgrade certifi` in that notebook and restart its kernel.
|
|
435
|
+
Networks using private CAs can supply a trusted bundle through `SSL_CERT_FILE`.
|
|
436
|
+
|
|
437
|
+
In **Group & summarise**, select the grouping columns, then select a column in
|
|
438
|
+
**Key order** and click **Move up** or **Move down**. The chosen sequence controls
|
|
439
|
+
the grouping columns in the result and in Pandas, PySpark, and Spark SQL exports;
|
|
440
|
+
saved steps retain it when edited. Grouping-key order does not sort result rows.
|
|
441
|
+
To sort a grouped result, add the grouping step, then add a **Select** step with
|
|
442
|
+
**Order by** configured.
|
|
443
|
+
|
|
444
|
+
**Group & summarise** also has an optional **Summary alias** field. For example,
|
|
445
|
+
group by `sex`, choose **Sum** on `total_bill`, and enter `total_bills` to produce
|
|
446
|
+
one total per sex with that column name. Leave the alias blank to use the default
|
|
447
|
+
name (`total_bill_sum` or `row_count`). Aliases are preserved in saved steps and
|
|
448
|
+
all code exports, and must differ from grouping column names.
|
|
449
|
+
|
|
450
|
+
To explore a relationship, open **Inspect a column** and enable **Compare columns**.
|
|
451
|
+
The existing column selector becomes **Column (Y)** and **Against (X)** selects
|
|
452
|
+
the second numeric column. For the tips data, select `tip` on Y and `total_bill`
|
|
453
|
+
on X. Choose **Scatter (Y vs X)** or **Two curves vs samples** in **View**.
|
|
454
|
+
Both replace the single-column view in the same chart area; disable the switch
|
|
455
|
+
to return to the usual charts and statistics. The two-curve view uses sample
|
|
456
|
+
positions starting at 1 in source row order, with a legend and a shared value
|
|
457
|
+
axis. Missing values leave gaps independently in each curve. Each scatter point
|
|
458
|
+
is one source row. Missing or infinite pairs are skipped; large plots show up to
|
|
459
|
+
5,000 points sampled evenly by row position, with counts displayed above the
|
|
460
|
+
plot. Comparing columns does not change query settings or results.
|
|
461
|
+
|
|
462
|
+
Version information is available through `tablelab.__version__` and
|
|
463
|
+
`python -m tablelab --version` (or `tablelab --version`). See
|
|
464
|
+
[CHANGELOG.md](CHANGELOG.md) for release changes and
|
|
465
|
+
[RELEASING.md](RELEASING.md) for versioning and build instructions.
|