← tsb playground

attrs — User-Defined Metadata

Attach arbitrary key→value metadata to any Series or DataFrame — mirrors pandas.DataFrame.attrs and pandas.Series.attrs.

Design note: Because tsb objects are immutable (their data, index, and dtype are frozen), attrs are stored in a WeakMap registry rather than as instance properties. This means attrs are attached & detached without touching the object itself, and garbage-collected automatically when the object is collected.

Basic usage

import {
  getAttrs, setAttrs, updateAttrs, copyAttrs, withAttrs,
  clearAttrs, hasAttrs, getAttr, setAttr, deleteAttr,
  attrsCount, attrsKeys, mergeAttrs,
} from "tsb";
import { DataFrame, Series } from "tsb";

// ─── annotate a DataFrame ─────────────────────────────────────────────────
const df = DataFrame.fromColumns({
  temperature: [22.1, 23.5, 21.8],
  humidity:    [55, 60, 58],
});

setAttrs(df, {
  source: "weather_station_42",
  unit:   "Celsius",
  notes: "Morning readings",
});

getAttrs(df);
// → { source: "weather_station_42", unit: "Celsius", notes: "Morning readings" }

getAttr(df, "unit");     // → "Celsius"
getAttr(df, "missing");  // → undefined
attrsCount(df);          // → 3
attrsKeys(df);           // → ["source", "unit", "notes"]
hasAttrs(df);            // → true

Merging and updating

// updateAttrs merges new keys, preserves existing
updateAttrs(df, { version: 2, notes: "Updated notes" });
getAttrs(df);
// → { source: "weather_station_42", unit: "Celsius", notes: "Updated notes", version: 2 }

// setAttr / deleteAttr for single keys
setAttr(df, "sensor_id", "WS-042");
deleteAttr(df, "notes");
getAttrs(df);
// → { source: "weather_station_42", unit: "Celsius", version: 2, sensor_id: "WS-042" }

Propagating metadata to derived objects

// copyAttrs: copy all attrs from one object to another
const s = new Series({ data: [22.1, 23.5, 21.8], name: "temperature" });
setAttrs(s, { unit: "Celsius", source: "sensor_A" });

const derived = new Series({ data: [71.8, 74.3, 71.2], name: "fahrenheit" });
copyAttrs(s, derived);
getAttrs(derived);
// → { unit: "Celsius", source: "sensor_A" }

// Then update the copy
setAttr(derived, "unit", "Fahrenheit");
getAttrs(derived);  // → { unit: "Fahrenheit", source: "sensor_A" }
getAttrs(s);        // → { unit: "Celsius", source: "sensor_A" }  ← unchanged

Fluent helper — withAttrs

// withAttrs sets attrs and returns the same object reference
// Handy for inline annotation
const annotated = withAttrs(
  DataFrame.fromColumns({ x: [1, 2, 3] }),
  { source: "lab_experiment", date: "2026-04-09" },
);

annotated === annotated;  // true — same reference, not a copy
getAttrs(annotated);
// → { source: "lab_experiment", date: "2026-04-09" }

Merging from multiple sources

// mergeAttrs: combine attrs from multiple objects into a target
const s1 = new Series({ data: [1, 2, 3], name: "a" });
const s2 = new Series({ data: [4, 5, 6], name: "b" });
setAttrs(s1, { source: "sensor_A", unit: "kg" });
setAttrs(s2, { source: "sensor_B", scale: 2.5 });

const combined = DataFrame.fromColumns({ a: [1, 2, 3], b: [4, 5, 6] });
mergeAttrs([s1, s2], combined);
// Later sources win on conflicts: source="sensor_B"
getAttrs(combined);
// → { source: "sensor_B", unit: "kg", scale: 2.5 }

Clearing metadata

setAttrs(df, { x: 1, y: 2 });
hasAttrs(df);   // → true
attrsCount(df); // → 2

clearAttrs(df);
hasAttrs(df);   // → false
getAttrs(df);   // → {}

API reference

FunctionDescription
getAttrs(obj)Return a shallow copy of all stored attrs (empty {} if none)
setAttrs(obj, attrs)Overwrite attrs completely with the given record
updateAttrs(obj, updates)Merge updates into existing attrs (existing keys preserved)
withAttrs(obj, attrs)Fluent: set attrs and return the same object
copyAttrs(source, target)Copy all attrs from source to target
mergeAttrs(sources[], target)Merge attrs from multiple sources; later sources win
clearAttrs(obj)Remove all attrs from obj
hasAttrs(obj)Return true if any attrs are set
getAttr(obj, key)Get a single attr value (undefined if missing)
setAttr(obj, key, value)Set a single attr, preserving other keys
deleteAttr(obj, key)Delete a single attr key
attrsCount(obj)Number of stored attr keys
attrsKeys(obj)Array of stored attr key names

Comparison with pandas

pandastsb
df.attrsgetAttrs(df)
df.attrs = {"k": "v"}setAttrs(df, { k: "v" })
df.attrs["k"] = "v"setAttr(df, "k", "v")
df.attrs["k"]getAttr(df, "k")
del df.attrs["k"]deleteAttr(df, "k")
df.attrs.update(d)updateAttrs(df, d)
df.attrs.clear()clearAttrs(df)