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.
Files changed (43) hide show
  1. tablelab-0.5.0/.gitignore +42 -0
  2. tablelab-0.5.0/CHANGELOG.md +64 -0
  3. tablelab-0.5.0/LICENSE +21 -0
  4. tablelab-0.5.0/PKG-INFO +465 -0
  5. tablelab-0.5.0/README.md +420 -0
  6. tablelab-0.5.0/RELEASING.md +67 -0
  7. tablelab-0.5.0/examples/data/sensor_log.csv +201 -0
  8. tablelab-0.5.0/examples/data/signals.csv +120 -0
  9. tablelab-0.5.0/examples/data/test_table1.csv +4 -0
  10. tablelab-0.5.0/examples/data/test_table2.csv +4 -0
  11. tablelab-0.5.0/examples/tablelab_queries.ipynb +153 -0
  12. tablelab-0.5.0/pyproject.toml +60 -0
  13. tablelab-0.5.0/src/tablelab/__init__.py +72 -0
  14. tablelab-0.5.0/src/tablelab/__main__.py +64 -0
  15. tablelab-0.5.0/src/tablelab/app.py +431 -0
  16. tablelab-0.5.0/src/tablelab/charts.py +242 -0
  17. tablelab-0.5.0/src/tablelab/code_export.py +545 -0
  18. tablelab-0.5.0/src/tablelab/column_inspector.py +303 -0
  19. tablelab-0.5.0/src/tablelab/figures.py +101 -0
  20. tablelab-0.5.0/src/tablelab/file_readers.py +129 -0
  21. tablelab-0.5.0/src/tablelab/filepicker.py +195 -0
  22. tablelab-0.5.0/src/tablelab/helpers/__init__.py +50 -0
  23. tablelab-0.5.0/src/tablelab/helpers/data.py +30 -0
  24. tablelab-0.5.0/src/tablelab/helpers/plotting.py +31 -0
  25. tablelab-0.5.0/src/tablelab/helpers/widgets.py +5 -0
  26. tablelab-0.5.0/src/tablelab/missing_values.py +97 -0
  27. tablelab-0.5.0/src/tablelab/paged_preview.py +152 -0
  28. tablelab-0.5.0/src/tablelab/pipeline.py +202 -0
  29. tablelab-0.5.0/src/tablelab/query_app.py +1343 -0
  30. tablelab-0.5.0/src/tablelab/query_expressions.py +91 -0
  31. tablelab-0.5.0/src/tablelab/table.py +128 -0
  32. tablelab-0.5.0/tests/test_code_export.py +274 -0
  33. tablelab-0.5.0/tests/test_code_usability.py +83 -0
  34. tablelab-0.5.0/tests/test_column_relationship.py +235 -0
  35. tablelab-0.5.0/tests/test_group_alias.py +63 -0
  36. tablelab-0.5.0/tests/test_group_key_order.py +62 -0
  37. tablelab-0.5.0/tests/test_missing_values.py +133 -0
  38. tablelab-0.5.0/tests/test_pipeline.py +308 -0
  39. tablelab-0.5.0/tests/test_query_app.py +769 -0
  40. tablelab-0.5.0/tests/test_query_extensions.py +183 -0
  41. tablelab-0.5.0/tests/test_release.py +38 -0
  42. tablelab-0.5.0/tests/test_smoke.py +362 -0
  43. 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.
@@ -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.