npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

framekit-js

v0.2.0

Published

The TypeScript-first DataFrame library for Node.js

Downloads

33

Readme

FrameKit

CI Bench Smoke Bench Nightly npm License: MIT TypeScript Node.js GitHub issues

DataFrames for TypeScript that don't make you wish you were using Python.

FrameKit is a TypeScript-first DataFrame engine for Node.js. Strong types, predictable null semantics, lazy and eager execution, and production-grade I/O — without the "just use pandas" compromise.

Try it in the browser

framekit-js Playground →

Write TypeScript directly in the browser — no install, no setup. Monaco editor with FrameKit types, live execution via esbuild-wasm, and a table view of results.

Table of Contents

Why FrameKit

  • Strong TypeScript ergonomics for both row-level and expression-level transformations.
  • Shared semantics across eager and lazy execution.
  • Practical data engineering surface: joins, reshape, aggregations, window ops, and streaming formats.
  • Compatibility layer (framekit-js/compat) to ease migration from Arquero-style pipelines.

Feature Overview

| Area | Highlights | | ------------------ | --------------------------------------------------------------------------- | | DataFrame core | select, drop, filter, sortBy, groupBy, join, unique, sample | | Expressions | arithmetic, comparison, logical, null helpers, string/date accessors | | Aggregations | sum, mean, count, min, max, std, corr, list/mode, first/last | | Reshape | pivot, melt, explode, spread, unroll, transpose, concat | | Utility transforms | assign, relocate, lookup, reify, impute, derive, apply | | Lazy execution | query plans, optimizer passes, explain support, eager executor | | I/O | CSV, JSON, NDJSON, Arrow, Excel, Parquet, SQL export |

Install

npm install framekit-js

60-Second Example

import { DataFrame, col, op } from 'framekit-js';

const sales = DataFrame.fromRows([
  { region: 'EU', product: 'A', qty: 2, price: 10 },
  { region: 'EU', product: 'B', qty: 1, price: 25 },
  { region: 'US', product: 'A', qty: 4, price: 10 },
  { region: 'US', product: 'B', qty: 3, price: 25 },
]);

const result = sales
  .withColumn('revenue', col<number>('qty').mul(col<number>('price')))
  .groupBy('region')
  .agg({
    total_revenue: col('revenue').sum(),
    avg_revenue: col('revenue').mean(),
  })
  .sortBy('total_revenue', 'desc');

const quality = sales.groupBy().agg({
  qty_price_corr: op.corr(col('qty'), col('price')),
});

console.log(result.toArray());
console.log(quality.toArray());

Expected output:

// result.toArray()
[
  { region: 'US', total_revenue: 115, avg_revenue: 57.5 },
  { region: 'EU', total_revenue: 45,  avg_revenue: 22.5 }
]

// quality.toArray()
[
  { qty_price_corr: 0.7071067811865476 }
]

Eager and Lazy APIs

import { DataFrame, col } from 'framekit-js';

const source = DataFrame.fromRows([
  { city: 'Rome', temp: 26 },
  { city: 'Milan', temp: 31 },
  { city: 'Turin', temp: 28 },
]);

const eager = source.filter(col<number>('temp').gt(27));

const lazy = source.lazy().filter(col<number>('temp').gt(27)).select('city', 'temp').collect();

I/O Matrix

| Format | Read | Write | | ------------------ | ---- | ----- | | CSV | Yes | Yes | | JSON | Yes | Yes | | NDJSON (streaming) | Yes | Yes | | Arrow IPC | Yes | Yes | | Excel | Yes | Yes | | Parquet | Yes | Yes | | SQL (INSERT text) | No | Yes |

Core and Compat APIs

  • framekit-js: native API (DataFrame, expressions, lazy plans, I/O).
  • framekit-js/compat: migration-friendly verbs (derive, rollup, fold, orderby) and helpers (all, not, range, desc).

Start here for migration examples: docs/guides/migration-arquero.md.

Documentation

  • Getting started: docs/getting-started/quickstart.md
  • Guides: docs/guides/
  • Cookbook examples: docs/cookbook/
  • API references: docs/reference/

Comparison

| | FrameKit | Arquero | Danfo.js | Polars (Node) | | ---------------- | -------- | -------- | -------- | ------------- | | TypeScript-first | Yes | No | Partial | No (Rust FFI) | | Lazy execution | Yes | No | No | Yes | | Expression API | Yes | No | No | Yes | | Null semantics | Explicit | Implicit | Implicit | Explicit | | I/O formats | 7 | 2 | 4 | 6 | | Browser support | Yes | Yes | Yes | No | | Zero native deps | Yes | Yes | No | No |

Benchmarks and Quality

  • Benchmark compare runners and outputs live under tests/benchmarks/ and benchmarks/results/.
  • CI includes smoke and nightly benchmark workflows.
  • Regression checks are available in the benchmark harness.

Latest Benchmark Snapshot (FrameKit vs Arquero)

Current checked-in snapshot (BENCH_ROWS=50000, BENCH_ITERS=10, BENCH_WARMUP=3):

| Operation | FrameKit Median (ms) | Arquero Median (ms) | Relative (FrameKit/Arquero) | Source | | --------- | -------------------: | ------------------: | --------------------------: | ----------------------------------------- | | Filter | 26.9228 | 36.6342 | 0.73x | benchmarks/results/compare-filter.json | | Sort | 25.5620 | 50.6992 | 0.50x | benchmarks/results/compare-sort.json | | GroupBy | 3.9674 | 5.0675 | 0.78x | benchmarks/results/compare-groupby.json | | Join | 20.4444 | 61.5447 | 0.33x | benchmarks/results/compare-join.json | | Reshape | 17.2577 | 65.6563 | 0.26x | benchmarks/results/compare-reshape.json | | Window | 22.2838 | 64.1068 | 0.35x | benchmarks/results/compare-window.json |

Run Benchmarks Locally

# Fast smoke check
npm run bench:smoke

# Full compare suite
npm run bench:full

For human-readable per-operation reports, see benchmarks/results/*.md.

Benchmark outputs are directional and environment-sensitive; validate on your own hardware and runtime before drawing hard conclusions.

Project Standards

  • Changelog: CHANGELOG.md
  • Contributing guide: CONTRIBUTING.md
  • Security policy: SECURITY.md
  • Code of conduct: CODE_OF_CONDUCT.md

License

MIT - see LICENSE.