> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ovalbee.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ovalbee.com/_mcp/server.

# Compute stats

> Compute per-annotation and per-object statistics for a dataset and store them as columnar files that other nodes can query cheaply.

## Overview

Parses a dataset's annotations once and stores what they contain — object classes,
geometries, areas, box sides, and tags — as columnar files in workspace storage.
Other nodes, such as [Data Quality Control](/node-library/nodes/dataset-ops-annotation-quality)
and [Filter images](/node-library/nodes/filter-filter-images), read those files
instead of downloading and parsing the annotations again.

Statistics are keyed to the annotation, and annotations are immutable, so every
annotation is parsed once ever. A rerun over an unchanged dataset computes nothing, and
datasets that share annotations — copies, splits, merges — share the stored rows.

Running this node is never required: consumers compute whatever the store is missing on
their own. Place it in a flow to pay the one-time parsing cost up front, for example on a
schedule or before a large filtering step.

```mermaid
flowchart LR
  dataset["Dataset"] --> stats["Compute stats"] --> store["Statistics store"]
```

## How it works

Lists the dataset's images with their annotation records, without downloading
annotation files.

Asks the statistics store which of those annotation ids it has never seen.

Downloads and parses only the missing annotations, in one batch.

Appends the new rows as parquet files and folds the accumulated files together when
too many have piled up.

## FAQ

#### Do I have to run this node before Filter images or Data Quality Control?

No. Consumers compute whatever the store is missing on their own. Running this node
first only moves the one-time parsing cost to a moment you choose.

#### What happens when annotations change?

Editing labels produces a new annotation with a new id, so the next run computes rows
for the new annotations only. Rows of annotations that left the dataset stay in the
store, and consumers ignore rows that no current annotation refers to.

#### Why does the badge show \`0 computed\`?

Every annotation of the dataset is already in the store. That is the normal state
after the first run.

## Inputs

**`Dataset`** `dataset` — required

Dataset whose annotations are measured. Annotations measured by an earlier run are skipped, so a rerun over an unchanged dataset does no work. Key: `DATASET`.

---

## Outputs

**`Statistics summary`** `string`

How many annotations were computed on this run. Shown on the node as a badge. Key: `STATS_SUMMARY`.

---

## JSON config

Machine-readable node interface for automation and advanced usage.

#### Show JSON

```json
{
  "name": "Compute stats",
  "description": "Compute per-annotation and per-object statistics for a dataset and store them as columnar files that other nodes can query cheaply.",
  "category": "Datasets",
  "namespace": null,
  "templateKey": "dataset_ops/compute_stats",
  "version": "v1",
  "inputs": [
    {
      "key": "DATASET",
      "label": "Dataset",
      "type": "dataset",
      "description": "Dataset whose annotations are measured. Annotations measured by an earlier run are skipped, so a rerun over an unchanged dataset does no work.",
      "required": true,
      "default": null,
      "visibleWhen": null,
      "options": {
        "creatable": false
      }
    }
  ],
  "outputs": [
    {
      "key": "STATS_SUMMARY",
      "label": "Statistics summary",
      "type": "string",
      "description": "How many annotations were computed on this run.",
      "artifact": false,
      "badge": true,
      "badgeOpens": null,
      "hidden": false
    }
  ]
}
```