Skip to main content

DataFolio

Python 3.10+ Docs

A small, self-documenting home for the data behind one analysis.

You already have the objects: a feature table, some labels, an array of embeddings, a fitted model, a parameter dict, a QC plot. DataFolio gives them one directory, one name each, and one sentence each explaining what they are — then hands them back by name months later, from any notebook.

from datafolio import DataFolio

folio = DataFolio("analysis/experiment-12")

folio.add("features", features, description="One row per neuron; normalized morphology")
folio.add("labels", labels, description="Manual labels after the March review")
folio.add("params", {"alpha": 0.1, "seed": 7})
folio.add_model("classifier", clf, inputs=["features", "labels"])
# A different notebook, six months later. One path, no filenames.
folio = DataFolio("analysis/experiment-12")

folio.describe()
features = folio.get("features")
clf = folio.get_model("classifier")

Install

pip install datafolio            # core
pip install 'datafolio[polars]'  # + lazy scans and Polars frames

Python 3.10+.

Who it's for

One researcher, or a small team sharing mostly read-only work, holding a few to a few dozen understandable objects per analysis. It assumes you are comfortable in pandas, Polars, numpy, and scikit-learn and do not want another framework between you and them.

Good fit when you want to stop writing pd.read_parquet(BASE / "features_v3_reviewed.parquet") in every notebook, remember which of five similar files the paper used, keep one analysis's objects together, or hand a colleague a single path.

What you get

One write path, one read path. add() picks the storage format from the object's type; get() reads the catalog and returns the matching Python object.

folio.add("table", dataframe)            # pandas / Polars / LazyFrame -> Parquet
folio.add("embeddings", array)           # numpy -> .npy
folio.add("params", {"alpha": 0.1})      # dict / list / scalar / str -> JSON
folio.add_model("classifier", clf)       # -> joblib (or skops)
folio.add_file("plots/qc.png")           # -> the file, unchanged
folio.reference_table("raw", "gs://lab-data/raw.parquet")   # link, don't copy

Descriptions live next to the data. The most valuable metadata is usually one sentence saying which of several near-identical files this is. It is stored in the catalog, shown by describe(), and readable by people who never install the package.

Ordinary files, not a container format.

experiment-12/
├── items.json                    # the authoritative catalog (+ metadata + snapshots)
├── CONTENTS.md                   # derived, human-readable inventory
├── README.md                     # how to read this directory without datafolio
├── tables/features--r2.parquet
├── models/classifier--r8.joblib
└── artifacts/params--r5.json

Local or cloud, same code. DataFolio("gs://team-analysis/experiment-12").

Lineage, snapshots, and a CLI when you need them:

folio.add("predictions", preds, inputs=["classifier", "holdout"])
folio.create_snapshot("paper-v1", description="Figures 2–4 in the submission")
datafolio describe
datafolio snapshot status

What it is not

Not a database or query engine, not a workflow orchestrator, not data version control, not an experiment tracker, not a multi-writer system, not a backup. Many readers, one writer — treat a cloud folio as single-writer. Comfortable at a few dozen items per folio, not thousands.

DataFolio's rule is to be as lightweight as possible and hand off to better tools as soon as possible: big tables go to Polars as a lazy scan, or to you as a path. See What DataFolio is not for the full list, including the sharp edges worth knowing before you rely on it.

Documentation

Read in this order:

  1. Your first folio — ten minutes
  2. Everyday patterns
  3. Tables: big, external, and lazy
  4. Models
  5. Sharing a folio
  6. Snapshots
  7. Reading a folio without DataFolio
  8. What DataFolio is not

Reference: API cheat sheet · CLI · Migrating from 1.x

Development

uv sync
poe test                      # pytest with coverage
uv run ruff check src/ tests/
poe doc-preview               # local docs server

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

datafolio-2.0.0.tar.gz (105.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

datafolio-2.0.0-py3-none-any.whl (120.6 kB view details)

Uploaded Python 3

File details

Details for the file datafolio-2.0.0.tar.gz.

File metadata

  • Download URL: datafolio-2.0.0.tar.gz
  • Upload date:
  • Size: 105.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for datafolio-2.0.0.tar.gz
Algorithm Hash digest
SHA256 82d43015185e191575e80b50e0ce069556f1c829d16f5b4404be425d7a7cdb7e
MD5 10c234ba66148c84aa7f57f52ba5979b
BLAKE2b-256 44d2ee52acb189ac731d75123dafea04e3f5f541ee23ef585dfd8faba1a94b9a

See more details on using hashes here.

File details

Details for the file datafolio-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: datafolio-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 120.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for datafolio-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2f7dcb493d6f699621f09a426984972214bf39fa52385c059e1547998156491c
MD5 9d500075cdabb748c988182e3724cff1
BLAKE2b-256 db0b7bfe1f9c5ee17f23e608c3243477b74e612e84e883b0a3decf847267da80

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page