Open-source project
hosseinmoein/DataFrame avatar
hosseinmoein/DataFrame

hosseinmoein/DataFrame: a templatized C++ container for tabular analysis

C++ DataFrame for statistical, financial, and ML analysis in modern C++

2,983 stars360 forksC++BSD-3-Clause

At a glance

What is it?
This is a header-only-style C++23 library that puts columns first, supports heterogeneous and multidimensional column types, and ships analytical algorithms as visitors. It is a fit for quant and C++ teams that want tabular work without a Python runtime, and a poor fit for anyone who needs a stable ABI or a mature ecosystem of third-party integrations.
Who is it for?
Adopt it if your team already builds C++23 and wants columnar tabular operations and financial or statistical algorithms in the same binary as your trading or simulation code. Do not adopt it if you need a stable ABI across compiler versions, a large third-party ecosystem, or a library whose behaviour is specified outside its own documentation.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly C++, 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 problem it targets: tabular work without leaving C++

The README frames the library as an answer to a specific gap: data manipulation and analysis functionality that exists in Python's Pandas or R's data.frame, made available inside C++. The stated audience is data scientists, quant traders, and C++ developers who need tabular processing without what the README calls Python overhead. That phrasing matters. The pitch is not that C++ is a better analysis language in the abstract. It is that a quant pipeline, a simulation, or a low-latency service already lives in C++, and moving rows through a Python process to filter, group, or compute a moving average adds a boundary the author does not want. The library is described as a templatized and heterogeneous container, and the README's own comparison is an Excel spreadsheet or a SQL table, with the qualification that a C++ DataFrame need not be two-dimensional at all. Columns can be vectors of any type, including DataFrames or other containers. That single design decision is what separates it from a fixed-schema table abstraction, and it is also the source of most of the trade-offs discussed below.

Columns as first-class citizens, and what that buys

The README states that columns are the first-class citizens of the DataFrame, meaning operations and access to columns are more efficient and easier than dealing with data row by row. This is the architectural claim the rest of the library rests on. A row-oriented container forces every filter and every aggregate to walk records and project fields; a column-oriented one lets an operation touch only the columns it names. The README lists the operations this enables: slicing in many ways, join, merge, group-by, cross tabulation, pivot, multi-column sort, and custom pick and delete. It also states that the API is designed to be open-ended so that custom algorithms can be included. The heterogeneity claim is the more unusual one. Because a column can hold any type, including another DataFrame, the structure is not limited to the two dimensions a SQL table implies. The README says many of the bundled algorithms work with both scalar and multidimensional datasets. Whether that generality is worth its cost is a judgement the documentation does not make for you. Templates that accept arbitrary column types mean errors surface at instantiation, not at a documented interface boundary.

Analytics arrive as visitors, not as free functions

The analytical layer is delivered as visitors. The README describes a large collection of algorithms in that form, ranging from basic statistics such as Mean, Stdev, and Moving Averages up to PCA, Polynomial Fit, FFT, and Eigens, plus what it calls a good collection of trading indicators. The visitor pattern is a deliberate choice: it keeps the algorithm separate from the container, and it is what allows the same algorithm to run against scalar and multidimensional data. It also gives a clean extension point, since the README states you can add your own algorithms easily. The practical consequence is that the algorithm surface is not a fixed set of member functions you can look up in one place. It is a set of visitor types, and the documentation page is where the full list with code samples lives. The README points to examples/hello_world.cc, a CheatSheet.pdf, and the generated HTML documentation at the project's GitHub Pages site. For evaluation purposes, the visitor catalogue is the thing to read closely, because the library's value to a quant desk is concentrated in whether the specific indicator or decomposition you need is present and documented for your column types.

Multithreading is built into the API, with the usual caveats

The README states that DataFrame employs extensive multithreading in almost all its APIs for large datasets, and that this makes it especially suitable for analyzing large datasets. Two things are worth separating here. The first is that threading is internal to the library, not something the caller schedules. You do not opt into a thread pool per operation; the API decides. That is convenient and it is also a constraint, because the concurrency behaviour is not something the README documents in terms of thread counts, thresholds, or determinism. The second is the qualifier: for large datasets. Small frames presumably fall below whatever threshold the implementation uses, but the README does not state where that line sits. If your workload is latency-sensitive and you need predictable core usage, this is a design property to test against your own data rather than assume. Nothing in the supplied material gives a benchmark, a speedup figure, or a comparison against a single-threaded baseline, so treat the performance claim as a design statement rather than a measured one.

Getting it into a build: C++23 and two package managers

The constraints are visible in the badges at the top of the README: the project advertises C++23, and it is packaged for both Conan Center and vcpkg. So the realistic entry paths are a Conan dependency on dataframe, a vcpkg port of the same name, or a source build from the repository. The README does not reproduce the exact conanfile or vcpkg.json snippet in the material available here, so the precise version pin and any options belong in the package registry entry rather than in this article. What can be stated is the shape of the integration: this is a compiled C++ library consumed through a package manager or vendored into your tree, not a runtime dependency you install separately. The C++23 requirement is the first gate. If your toolchain is pinned to C++17 or C++20 for ABI or vendor reasons, that gate is not negotiable without patching, and the README gives no indication of a lower-standard build. The second gate is platform coverage. The CI badge in the README points at AppVeyor, which suggests Windows builds are exercised, but the material here does not enumerate supported compilers or operating systems beyond that.

Where it is the wrong tool

The templatized, heterogeneous design has a cost that the README does not dwell on. A library whose columns can hold any type, including nested DataFrames, cannot offer a stable binary interface across compilers and standard-library versions in the way a fixed-layout C API can. If you are shipping a shared library to third parties, or if you need to pass frames across a plugin boundary compiled by a different toolchain, this design works against you. The second limitation is scope. This is an in-memory library. The README describes it as being for in-memory data exploration, transformation, and statistical analysis. There is no mention of out-of-core execution, spill-to-disk, or a query planner that can push work down to a storage layer. If your dataset does not fit in RAM, the library's own framing does not claim to help. The third is ecosystem. The README's comparison to Pandas, data.frame, and Polars is about functionality, not about the surrounding tooling: file format readers, notebook integration, plotting, and the long tail of community packages that exist for those systems. Moving to this library means writing or sourcing that layer yourself.

How it differs from Polars and Pandas in approach

The README explicitly positions the library against Pandas, R's data.frame, and Polars, claiming that the depth and breadth of functionality in C++ DataFrame alone exceeds those three combined. That claim is the author's and cannot be verified from the material here. The more useful comparison is architectural. Pandas and Polars are runtime libraries with a Python surface, a defined set of dtypes, and a query execution layer that Polars exposes as an explicit engine. C++ DataFrame is a compile-time templated container with no dtype enumeration: the column type is whatever C++ type you instantiated, and the algorithm is a visitor over it. That difference cuts both ways. You get zero-cost abstraction over your own types and no marshalling between a Python object model and a C++ one. You lose the ability to load a frame whose schema you did not know at compile time without writing that dispatch yourself, and you lose the interactive workflow that makes Pandas and Polars productive for exploratory work. A team choosing between them is really choosing between compile-time typing and runtime typing, not between two implementations of the same thing.

Maintenance, releases, and the licence

The release cadence visible in the material is roughly every two months: 4.0.1 in April 2026, 4.0.2 in June 2026, 4.1.0 in August 2026, with the last push to master in September 2026 and the repository not archived. That is an actively maintained project, though the material does not describe a support policy, a deprecation window, or a compatibility guarantee between minor versions. For a C++ library consumed through Conan or vcpkg, the upgrade cost is the usual one: a version bump, a rebuild, and whatever template errors the new release surfaces in your instantiation sites. The licence is BSD-3-Clause, which the README reproduces in full at the top. In practical terms that permits redistribution in source and binary form provided the copyright notice, the list of conditions, and the disclaimer are retained, and it forbids using the author's name or the names of contributors to endorse derived products without permission. The usual disclaimer of warranty applies. This is a permissive licence with a name-endorsement clause, and if you redistribute binaries you need to carry the notice; for anything beyond that, consult your own counsel rather than this article.

Editorial conclusion

Adopt it if your team already builds C++23 and wants columnar tabular operations and financial or statistical algorithms in the same binary as your trading or simulation code. Do not adopt it if you need a stable ABI across compiler versions, a large third-party ecosystem, or a library whose behaviour is specified outside its own documentation. Before committing, verify three things: that your toolchain satisfies the C++23 requirement the badges state, that the Conan or vcpkg package builds on your target platform, and that the specific visitor you depend on (PCA, FFT, polynomial fit, or a trading indicator) is documented for the column types you actually use.

Official sources

  1. hosseinmoein/DataFrame on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Community notes

Community notes