deepbox/dataframe
Accessors & Indexing
String, datetime, categorical and multi-level index helpers: Series.str, Series.dt, Categorical, MultiIndex, toDatetime and dateRange.
- Accessors
Overview
series.strandseries.dtare accessors onSeries. Moststrmethods use the pandas names (upper,contains,extract,split,zfill), andgetDummiesreplacesget_dummies. Missing values stay missing.str.replace(pattern, replacement, regex = true)treats a string pattern as a regular expression, unlike pandas.- Dates are plain JavaScript
Datevalues, and every component is read in local time. There is no time zone support.toDatetimereads date-only and zone-less strings as local time and keeps the exact instant of strings withZor an offset. dateRange(start, periods, freq)takes a period count, not an end date. The frequencies areD,H,min,S,MSandYS.- The
dtmethods are camelCase (dayOfWeek(),isLeapYear(),dayName()). The lowercasedayofweek,dayofyear,weekofyearanddaysinmonthand the snake_case forms are deprecated. Categoricalholds values from a fixed list of categories, with optional ordering.MultiIndexbuilds hierarchical labels withfromArrays,fromTuplesandfromProduct.
DateFreq
typeFrequencies accepted by date_range: day, hour, minute, second, month start (MS) and year start (YS). Lowercase h and s are pandas' current spellings of H and S.
type DateFreq = "D" | "H" | "h" | "min" | "S" | "s" | "MS" | "YS";DateRoundFreq
typeFrequencies accepted by floor, ceil and round. Lowercase h and s are pandas' current spellings.
type DateRoundFreq = "D" | "H" | "h" | "min" | "S" | "s";Categorical
Categorical data type with optional ordering, modeled on pandas.Categorical.
Values are stored as integer codes that index into a category list, so a column with many repeated strings keeps each distinct string only once. Missing values (null or undefined on input) are stored as code -1.
Instances are immutable: every method that changes categories, order or data returns a new Categorical. The codes array is returned without copying for speed and must be treated as read-only.
Ordered categoricals support Categorical.compare, Categorical.min and Categorical.max.
import { Categorical } from 'deepbox/dataframe'; // Unordered categoricalconst colors = Categorical.from(['red', 'blue', 'red', 'green', 'blue']);console.log(colors.categories); // ['blue', 'green', 'red']console.log(colors.codes); // Int32Array [2, 0, 2, 1, 0] // Ordered categorical (e.g., size)const sizes = Categorical.from(['M', 'S', 'L', 'M', 'XL'], { categories: ['S', 'M', 'L', 'XL'], ordered: true});Members (25)
categories: readonly string[]Get the category list
codes: Int32ArrayGet the integer codes array (
-1marks a missing value).ordered: booleanWhether categories are ordered
length: numberNumber of elements
nCategories: numberNumber of unique categories (excluding missing)
static from(values: ReadonlyArray<string | null | undefined>, options?: { readonly categories?: readonly string[]; readonly ordered?: boolean; }): CategoricalCreate a Categorical from an array of values.
get(index: number): string | nullGet the string value at a given index.
toArray(): (string | null)[]Convert back to a string array.
isNull(): boolean[]Boolean mask marking missing values.
valueCounts(): Map<string, number>Count occurrences of each category.
addCategories(newCategories: readonly string[]): CategoricalAdd new categories to the category list.
removeCategories(removeCategories: readonly string[]): CategoricalRemove categories from the category list.
removeUnusedCategories(): CategoricalRemove categories that do not occur in the data.
reorderCategories(newOrder: readonly string[], options?: { readonly ordered?: boolean; }): CategoricalReorder categories.
setCategories(newCategories: readonly string[], options?: { readonly ordered?: boolean; }): CategoricalReplace the category list.
setOrdered(ordered: boolean): CategoricalSet whether categories are ordered.
asOrdered(): CategoricalReturn an ordered copy.
asUnordered(): CategoricalReturn an unordered copy.
renameCategories(mapping: Readonly<Record<string, string>> | ReadonlyMap<string, string> | ((category: string) => string)): CategoricalRename categories.
compare(a: string, b: string): numberCompare two values by their category order (only for ordered categoricals).
min(): string | nullSmallest value by category order.
max(): string | nullLargest value by category order.
sort(ascending?: boolean): CategoricalSort the values by category order.
memoryUsage(): numberEstimate memory usage in bytes.
toString(): stringText summary with the first and last values and the category list.
DateTimeAccessor
DateTime accessor for Series, providing vectorized date/time operations.
Accessed via series.dt. Operates element-wise on Series containing Date objects, ISO date strings, or epoch milliseconds. Null, undefined, NaN and empty-string elements propagate as null in the output.
Date-only and zone-less datetime strings are read as local time, and all component getters (year(), hour(), ...) report local time, like pandas' naive datetimes. Strings with an explicit Z or UTC offset denote an exact instant and are shown in local time.
const s = new Series([new Date('2024-01-15'), new Date('2024-06-20')]);s.dt.year(); // Series([2024, 2024])s.dt.month(); // Series([1, 6])s.dt.dayOfWeek(); // Series([0, 3]) (Mon=0 ... Sun=6)Members (47)
constructor(series: Series<unknown>)year(): Series<number | null>Calendar year of each date.
month(): Series<number | null>Month of each date, 1 (January) to 12 (December).
day(): Series<number | null>Day of the month, 1-31.
hour(): Series<number | null>Hour of the day, 0-23.
minute(): Series<number | null>Minute of the hour, 0-59.
second(): Series<number | null>Second of the minute, 0-59.
millisecond(): Series<number | null>Millisecond of the second, 0-999.
dayOfWeek(): Series<number | null>Day of week: Monday=0, Tuesday=1, ..., Sunday=6 (ISO convention).
dayofweek(): Series<number | null>deprecatedSame as DateTimeAccessor.dayOfWeek.
weekday(): Series<number | null>Alias of DateTimeAccessor.dayOfWeek.
dayOfYear(): Series<number | null>Day of year: 1-366.
dayofyear(): Series<number | null>deprecatedSame as DateTimeAccessor.dayOfYear.
weekOfYear(): Series<number | null>ISO 8601 week number (1-53).
weekofyear(): Series<number | null>deprecatedSame as DateTimeAccessor.weekOfYear.
week(): Series<number | null>Alias of DateTimeAccessor.weekOfYear.
quarter(): Series<number | null>Quarter: 1-4.
isLeapYear(): Series<boolean | null>Whether the year is a leap year.
is_leap_year(): Series<boolean | null>deprecatedSame as DateTimeAccessor.isLeapYear.
daysInMonth(): Series<number | null>Days in the month of each date.
days_in_month(): Series<number | null>deprecatedSame as DateTimeAccessor.daysInMonth.
daysinmonth(): Series<number | null>deprecatedSame as DateTimeAccessor.daysInMonth.
isMonthStart(): Series<boolean | null>Whether each date is the first day of its month.
is_month_start(): Series<boolean | null>deprecatedSame as DateTimeAccessor.isMonthStart.
isMonthEnd(): Series<boolean | null>Whether each date is the last day of its month.
is_month_end(): Series<boolean | null>deprecatedSame as DateTimeAccessor.isMonthEnd.
isQuarterStart(): Series<boolean | null>Whether each date is the first day of a quarter.
is_quarter_start(): Series<boolean | null>deprecatedSame as DateTimeAccessor.isQuarterStart.
isQuarterEnd(): Series<boolean | null>Whether each date is the last day of a quarter.
is_quarter_end(): Series<boolean | null>deprecatedSame as DateTimeAccessor.isQuarterEnd.
isYearStart(): Series<boolean | null>Whether each date is January 1.
is_year_start(): Series<boolean | null>deprecatedSame as DateTimeAccessor.isYearStart.
isYearEnd(): Series<boolean | null>Whether each date is December 31.
is_year_end(): Series<boolean | null>deprecatedSame as DateTimeAccessor.isYearEnd.
dayName(): Series<string | null>English weekday name of each date ("Monday", ...).
day_name(): Series<string | null>deprecatedSame as DateTimeAccessor.dayName.
monthName(): Series<string | null>English month name of each date ("January", ...).
month_name(): Series<string | null>deprecatedSame as DateTimeAccessor.monthName.
timestamp(): Series<number | null>Convert each date to epoch milliseconds (UTC based, independent of the local zone).
isoformat(): Series<string | null>Convert each date to an ISO 8601 string in UTC, such as
"2024-01-01T12:00:00.000Z".strftime(fmt: string): Series<string | null>Format each date using a strftime-style pattern, in local time.
date(): Series<Date | null>Truncate to date only (midnight).
normalize(): Series<Date | null>Alias of DateTimeAccessor.date, like pandas'
normalize().time(): Series<string | null>Extract the time portion as "HH:MM:SS".
floor(freq: DateRoundFreq): Series<Date | null>Floor each date to the start of the given frequency.
ceil(freq: DateRoundFreq): Series<Date | null>Ceil each date to the next boundary of the given frequency.
round(freq: DateRoundFreq): Series<Date | null>Round each date to the nearest boundary of the given frequency.
MultiIndex
Hierarchical (multi-level) index for DataFrames.
A MultiIndex represents a composite key made of multiple levels, enabling hierarchical row or column labeling. Each level is a separate array of labels, and the combination of labels across levels uniquely identifies each row.
import { MultiIndex } from 'deepbox/dataframe'; // Create from arraysconst mi = MultiIndex.fromArrays( [['US', 'US', 'UK', 'UK'], [2020, 2021, 2020, 2021]], ['country', 'year']);console.log(mi.length); // 4console.log(mi.nlevels); // 2console.log(mi.get(0)); // ['US', 2020] // Create from tuplesconst mi2 = MultiIndex.fromTuples( [['US', 2020], ['US', 2021], ['UK', 2020], ['UK', 2021]], ['country', 'year']);Members (20)
length: numberNumber of entries
nlevels: numberNumber of levels
names: readonly string[]Level names
levels: ReadonlyArray<readonly (string | number)[]>Label arrays, one per level.
isUnique: booleanTrue when no two entries have the same label tuple.
static fromArrays(arrays: ReadonlyArray<readonly (string | number)[]>, names?: readonly string[]): MultiIndexCreate a MultiIndex from separate arrays for each level.
static fromTuples(tuples: ReadonlyArray<readonly (string | number)[]>, names?: readonly string[]): MultiIndexCreate a MultiIndex from an array of tuples.
static fromProduct(levels: ReadonlyArray<readonly (string | number)[]>, names?: readonly string[]): MultiIndexCreate a MultiIndex representing all combinations of the given levels (Cartesian product).
get(index: number): (string | number)[]Get the label tuple at a given position.
toTuples(): (string | number)[][]Get all label tuples as arrays.
getLevel(level: number | string): readonly (string | number)[]Get a specific level's values.
getLevelValues(level: number | string): (string | number)[]Get unique values at a specific level, in order of first appearance.
getPosition(labels: readonly (string | number)[]): numberFind the position of a given label tuple.
has(labels: readonly (string | number)[]): booleanWhether a full label tuple is present.
equals(other: MultiIndex): booleanWhether another MultiIndex has the same names, levels and labels in the same order.
select(partialLabels: Readonly<Record<string, string | number>>): number[]Select rows matching a partial label specification.
droplevel(level: number | string): MultiIndexDrop a level from the MultiIndex.
swaplevel(i: number | string, j: number | string): MultiIndexSwap two levels in the MultiIndex.
toFlatIndex(separator?: string): string[]Convert to a flat array of stringified tuples for use as DataFrame index.
toString(): stringDescribe the index: size, level names and the first five entries.
StringAccessor
String accessor for Series, providing vectorized string operations.
Accessed via series.str. Operates element-wise on string Series. Null/undefined elements propagate as null in the output. Any other non-string element raises a DataValidationError.
Lengths, padding widths and slice positions count Unicode code points (not UTF-16 units), as in pandas, so an emoji counts as one character.
const s = new Series(['hello', 'WORLD', null]);s.str.upper(); // Series(['HELLO', 'WORLD', null])s.str.lower(); // Series(['hello', 'world', null])s.str.contains('lo'); // Series([true, false, null])Members (43)
constructor(series: Series<unknown>)upper(): Series<string | null>Convert every string to upper case.
lower(): Series<string | null>Convert every string to lower case.
title(): Series<string | null>Capitalize the first letter of every word and lower-case the rest, like Python's
str.title().capitalize(): Series<string | null>Upper-case the first character and lower-case the rest.
swapcase(): Series<string | null>Swap the case of every character.
strip(chars?: string): Series<string | null>Remove characters from both ends.
lstrip(chars?: string): Series<string | null>Remove characters from the start.
rstrip(chars?: string): Series<string | null>Remove characters from the end.
contains(pat: string | RegExp, regex?: boolean, caseSensitive?: boolean): Series<boolean | null>Test whether each string contains a pattern anywhere.
startswith(pat: string): Series<boolean | null>Test whether each string starts with
pat(a literal string).endswith(pat: string): Series<boolean | null>Test whether each string ends with
pat(a literal string).match(pat: string | RegExp): Series<boolean | null>Test whether the pattern matches at the start of each string, like Python's
re.match.fullmatch(pat: string | RegExp): Series<boolean | null>Test whether the pattern matches each whole string.
replace(pat: string | RegExp, repl: string, regex?: boolean): Series<string | null>Replace every occurrence of a pattern.
split(pat?: string | RegExp, n?: number): Series<string[] | null>Split each string into a list of parts.
len(): Series<number | null>Number of characters (Unicode code points) in each string.
slice(start?: number, stop?: number, step?: number): Series<string | null>Slice each string with Python semantics (negative positions count from the end).
get(position: number): Series<string | null>Get the character at a position (negative positions count from the end).
extract(pat: string | RegExp, group?: number): Series<string | null>Extract one capture group of the first match in each string.
findall(pat: string | RegExp): Series<string[] | null>Find all non-overlapping matches of a pattern in each string.
find(sub: string): Series<number | null>Lowest position (in characters) at which
suboccurs, or -1 when absent.rfind(sub: string): Series<number | null>Highest position (in characters) at which
suboccurs, or -1 when absent.removeprefix(prefix: string): Series<string | null>Remove
prefixfrom the start of each string when present.removesuffix(suffix: string): Series<string | null>Remove
suffixfrom the end of each string when present.pad(width: number, side?: "left" | "right" | "both", fillchar?: string): Series<string | null>Pad each string to a minimum width.
center(width: number, fillchar?: string): Series<string | null>Center each string in a field of the given width.
ljust(width: number, fillchar?: string): Series<string | null>Left-align each string in a field of the given width, filling on the right.
rjust(width: number, fillchar?: string): Series<string | null>Right-align each string in a field of the given width, filling on the left.
zfill(width: number): Series<string | null>Pad each string with zeros on the left to the given width.
cat(sep?: string): stringJoin all non-null strings into one string.
getDummies(sep?: string): DataFrameSplit each string on
sepand build 0/1 indicator columns, one per distinct token, ordered alphabetically.get_dummies(sep?: string): DataFramedeprecatedSame as StringAccessor.getDummies.
repeat(times: number): Series<string | null>Repeat each string
timestimes.count(pat: string | RegExp): Series<number | null>Count the non-overlapping matches of a pattern in each string.
isalpha(): Series<boolean | null>True where every character is a letter (any script) and the string is not empty.
isdigit(): Series<boolean | null>True where every character is a digit (decimal digits of any script, plus superscript and subscript digits).
isdecimal(): Series<boolean | null>True where every character is a decimal digit (Unicode category Nd).
isnumeric(): Series<boolean | null>True where every character is numeric (Unicode category N, such as digits, fractions and Roman numerals).
isalnum(): Series<boolean | null>True where every character is a letter or a number.
isspace(): Series<boolean | null>True where every character is whitespace.
isupper(): Series<boolean | null>True where there is at least one cased letter and all cased letters are upper case.
islower(): Series<boolean | null>True where there is at least one cased letter and all cased letters are lower case.
dateRange
function dateRange(start: string | Date | number, periods: number, freq?: DateFreq, options?: SeriesOptions): Series<Date>;Generate a range of dates at a fixed frequency.
D steps by calendar days (the time of day is kept across DST changes); H, min and S step by elapsed time. MS and YS follow pandas: the first value is the first month (or year) start on or after start, keeping the time of day, and later values step one month (or year) at a time.
Parameters
startstring | Date | number- Start date (string, Date, or epoch ms)
periodsnumber- Number of periods to generate
freqoptionalDateFreq- Frequency: 'D' (day), 'H' (hour), 'min' (minute), 'S' (second), 'MS' (month start), 'YS' (year start)
optionsoptionalSeriesOptions- Series options (name, index) for the result
Returns
Series<Date>Series of Dates
Throws
InvalidParameterErrorIf periods is not a non-negative integer, start is missing, or freq is unknown
import { dateRange } from 'deepbox/dataframe';const dates = dateRange('2024-01-01', 5, 'D');// Series([Date(Jan 1), Date(Jan 2), ..., Date(Jan 5)])timedelta
function timedelta(left: Series<unknown>, right: Series<unknown>, unit?: "ms" | "S" | "min" | "H" | "D"): Series<number | null>;Compute the difference between two Date Series in the given unit.
Parameters
leftSeries<unknown>- Left operand Series of Dates
rightSeries<unknown>- Right operand Series of Dates
unitoptional"ms" | "S" | "min" | "H" | "D"- Unit for result: 'ms', 'S', 'min', 'H', 'D'
Returns
Series<number | null>Series<number | null> of differences (left - right) in the given unit, indexed like left. A null on either side gives null.
Throws
DataValidationErrorIf the Series lengths differInvalidParameterErrorIf unit is unknown
toDatetime
function toDatetime(data: ReadonlyArray<string | number | Date | null | undefined>, options?: SeriesOptions): Series<Date | null>;Parse an array of values to Date Series.
Details
Accepts strings (ISO 8601), epoch milliseconds (numbers), or Date objects. null, undefined, NaN and empty strings become null. Date-only and zone-less datetime strings are read as local time; strings with Z or an offset keep their exact instant. Out-of-range components such as 2024-02-30 throw. The returned Dates are new objects, never the input instances.
Parameters
dataReadonlyArray<string | number | Date | null | undefined>- Array of date-like values
optionsoptionalSeriesOptions- Series options (name, index)
Returns
Series<Date | null>Series of Date objects
Throws
DataValidationErrorIf an element cannot be parsed as a date
import { toDatetime } from 'deepbox/dataframe';const dates = toDatetime(['2024-01-01', '2024-06-15', '2024-12-31']);dates.dt.month(); // Series([1, 6, 12])These older spellings still work in 1.x. New code should use the names above.
date_rangePrefer dateRange.to_datetimePrefer toDatetime.
import { Categorical, DataFrame, Series, dateRange, toDatetime } from "deepbox/dataframe"; const words = new Series(["Deepbox", "v1.5.0", "Docs"]);const dates = toDatetime(["2026-01-01", "2026-02-01"]);const range = dateRange("2026-01-01", 3, "D"); const df = new DataFrame({ city: ["riyadh", "jeddah"], openedAt: dates.toArray(),}); console.log(words.str.upper().toString());console.log(words.str.contains("box").toString());console.log(dates.dt.month().toString(), dates.dt.dayName().toString());console.log(range.toString());console.log(df.toString());console.log(Categorical.from(["low", "high", "low"]).toString());Found a mistake? Open an issue.