Library / SDK
techascent/tech.ml.dataset avatar
techascent/tech.ml.dataset

tech.ml.dataset: A Functional Columnar DataFrame for the JVM

A Clojure high performance data processing system

761 stars34 forksClojureEPL-1.0

At a glance

What is it?
tech.ml.dataset (TMD) is a Clojure library for tabular data processing, positioned by its README as similar to Pandas or R's data.table but functional. It stores columns as primitive arrays, packed datetime types and string tables, and ships a Java API alongside the Clojure one.
Who is it for?
Adopt tech.ml.dataset if your team already writes Clojure and wants tabular work to stay inside the JVM without a Python or R process in the loop, and if you are prepared to treat the documentation site as the primary reference rather than the README.
Can I use it commercially?
Yes, with conditions. EPL-1.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly Clojure, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap TMD fills: tabular work without leaving the JVM

Most JVM teams that need a dataframe reach for a Python or R process and bridge to it. That bridge is where the operational cost lives: a second runtime to install, a serialization format to agree on, and a boundary that gets crossed on every call. tech.ml.dataset exists to remove that boundary. The README describes it as a Clojure library for tabular data processing similar to Python's Pandas or R's data.table, and states that it supports pragmatic data-intensive work on the JVM. The audience is therefore narrow and specific: Clojure engineers, and Java engineers willing to call the provided Java API, who are already on the JVM and would rather not add a Python process to their deployment. If your data work happens in a notebook and your team writes Python, nothing here is aimed at you. The README also frames a design choice rather than just a feature: unlike Python or R, TMD datasets are functional, which the README says makes them easier to reason about. That is a claim about mutation semantics, not about speed, and it is the single most consequential thing to understand before adopting it.

How the columnar storage actually saves memory

The mechanism the README names is columnar storage with primitive arrays, packed datetime types and string tables, and it links to a gist showing datasets shrinking in memory. Read that list as a sequence of decisions. Values live in columns, not rows, so a column of longs is a long array rather than a vector of boxed objects. Datetimes are packed rather than stored as generic objects. Strings go through a string table, which means repeated values are not repeated in memory. Each of these is a representation choice that reduces per-value overhead, and together they are the reason the README can point at a memory comparison at all. What the README does not give is a number, a threshold, or a rule for when the savings matter. The honest position is that the benefit scales with column width and value repetition: a table of unique long strings gains more from a string table than a table of distinct doubles does. The README also points to tech.v3.datatype, described as the underlying numeric subsystem, so the primitive-array machinery is a separate library that TMD builds on rather than something TMD implements itself. That matters for debugging, because a type or buffer error may surface from the subsystem rather than from TMD's own code.

Getting it running: Clojars coordinates and the require form

The README does not inline install snippets. It directs you to Clojars at https://clojars.org/techascent/tech.ml.dataset for instructions for lein, deps.edn and other build systems, so the exact coordinate string is something you read off that page rather than something this article can quote. What the README does show is the verification step, and it is worth copying because it exercises the reader, the dataset constructor and the printer in one expression. The example requires the namespace as tech.v3.dataset, then builds a dataset from the JVM system properties, mapping each entry to a map with :k and :v keys and truncating the value to 40 characters, and passes a second map with :dataset-name set to "My Truncated System Properties". The printed result shows the dataset name followed by a shape in brackets, and a table with :k and :v columns, with rows elided by an ellipsis. Two things are worth noting from that output. The constructor is tech.v3.dataset/->>dataset, a threaded form, and the dataset name is supplied as an option map rather than as a positional argument. If that expression prints a table, your classpath is correct. The README also documents a Java path: a javadoc for tech.v3.TMD and a sample program at java_test/java/jtest/TMDDemo.java in the repository. That is the route to check if you are calling TMD from Java rather than Clojure.

Where the documentation lives, and what that implies

The README spends more space on documentation links than on code, which is a signal about how the project expects to be learned. It names four destinations: a Getting Started topic, a Walkthrough with long-form examples of processing real data, a Quick Reference summarizing frequently used functions, and full API docs. The Getting Started page is explicitly called the best place to start. This is a deliberate structure, and it has a consequence for anyone evaluating TMD from the repository alone. The README is a signpost, not a manual. You will not learn the function set from it, and you should not try. The Quick Reference is where the frequently used functions are summarized, and the API docs are described as documenting every available function, so the split is between a curated short list and an exhaustive one. A second consequence: the README lists related projects with one-line descriptions, including tablecloth as an alternative API with some important extra features, tech.ml for simple regression and classification pathways, and tmducken as bindings to an in-process SQL database. Those are pointers to other repositories, not components of TMD, and treating them as part of the library will lead you to install things you did not intend to.

The release cadence problem, and what it means for pinning

No releases were retrieved for this repository, while the last push to master is dated 2026-09-04. The README carries a copyright line for 2023. Taken together, the picture is a project that is actively committed to but does not present a tagged release history in the material available here. That is a real operational constraint, not a stylistic one. If your build process assumes versioned artifacts with dated changelogs and upgrade notes, you will not find that structure described in the README, and you should confirm on Clojars what versions are actually published before you plan an upgrade path. The practical stance is to pin an exact version and treat upgrades as deliberate events with a test run, rather than floating a range. The README's own verification snippet is a reasonable smoke test to keep in your test suite for that purpose, since it touches the reader, the constructor and the printer. Beyond that, this article cannot tell you how often releases ship or what changed between them, because the material does not say.

When TMD is the wrong tool

The functional design is the limitation as much as the feature. The README presents functional datasets as easier to reason about, and that is true, but it also means the mental model is not the one most dataframe users arrive with. If your existing code mutates a frame in place, appending columns and reassigning, the translation to a functional style is real work, not a rename. The second case is the interactive one. TMD is a library you program against, and the README's documentation set is written pages plus API docs, not an interactive shell workflow. Teams whose data work is primarily exploratory in a notebook will find the shape of the tool mismatched to the shape of the task, and the README itself names tablecloth as an alternative API with extra features, which is the honest place to look first. The third case is non-JVM. The README describes TMD as a library for data-intensive work on the JVM and documents a Java API, so a Python or R shop gains nothing here. Finally, note the dependency direction: TMD sits on tech.v3.datatype, so a problem in the numeric subsystem is a problem you may have to trace outside TMD's own source.

Alternatives: tablecloth and the in-process SQL route

The README names two alternatives with different approaches, and the difference is worth stating precisely. Tablecloth is described as an alternative API with some important extra features, available at github.com/scicloj/tablecloth. The distinction is at the API layer rather than the storage layer: TMD supplies the dataset representation and the columnar machinery, and tablecloth offers a different surface over comparable work. If you find TMD's function set awkward, tablecloth is the README's own suggestion, which makes it the first thing to try rather than a fallback. The second alternative is tmducken, described as bindings to a high performance in-process SQL database. That is a genuinely different approach: instead of expressing operations through Clojure functions over a dataset, you express them as SQL and let the database engine plan and execute them. For teams whose transformations are already written as SQL, or whose queries benefit from a query planner, that is a different trade rather than a better or worse one. Neither alternative is a drop-in replacement for the other, and the README presents them as separate projects rather than as layers of one stack.

Licence and the maintenance question

TMD is distributed under the Eclipse Public License version 1.0 or, at your option, any later version, with copyright held by TechAscent, LLC. EPL-1.0 is a file-level copyleft licence, which is the same family used across much of the Clojure ecosystem, so for many JVM teams this will be uncontroversial. It is not a permissive licence in the MIT or Apache sense, and the choice between EPL-1.0 and a later version is offered to you rather than fixed. Whether that fits your distribution model is a question for your own counsel, not for this article. On maintenance, the material supports only a limited statement: the repository is not archived, the last push is dated 2026-09-04, and the README carries a 2023 copyright line. That is consistent with a maintained project, but it is not a statement about release frequency, backward compatibility, or how quickly issues are answered. There is a zulip stream and a slack channel listed for questions, plus the issue tracker, which is where you would go to find out. The upgrade cost you can actually plan for is the one described above: pin an exact version, keep the README's verification expression in your tests, and confirm published versions on Clojars when you decide to move.

Editorial conclusion

Adopt tech.ml.dataset if your team already writes Clojure and wants tabular work to stay inside the JVM without a Python or R process in the loop, and if you are prepared to treat the documentation site as the primary reference rather than the README. Do not adopt it if you need a stable tagged release cadence with dated changelogs, or if your data work is exploratory and interactive in the notebook sense, where tablecloth's API is the one the README itself points at as an alternative. Before committing, verify three things against the documentation site rather than this article: that the current group and artifact coordinates on Clojars match what your build tool expects, that the Java API in the javadoc covers the operations you need from a non-Clojure caller, and that the column types your data actually contains are among the packed types TMD supports. The library is EPL-1.0, the same licence family as much of the Clojure ecosystem, so check that against your own distribution model rather than assuming it is compatible.

Official sources

  1. Issues
  2. License: EPL-1.0
  3. README
  4. techascent/tech.ml.dataset on GitHub
Community notes

Community notes