Skip to main content

A Pythonic, zero-dependency vector and table library for interactive data exploration

Project description

serif

License: MIT Tests

Python in, Python out. Allowed to raise, not allowed to lie.

Serif is typed vectors and tables for Python, built around two promises: touching your data should feel like ordinary Python, and ambiguous operations should fail loudly.

Values stay Python values — int, float, str, date, None — so there is nothing to convert, unwrap, or remember. And serif does not silently coerce, mutate, or guess. When an operation has no clear meaning, it raises.

Vector provides the foundation. Table is the primary interface for exploration, modeling, and analysis.

30-Second Example

from serif import Table

t = Table({
    "price ($)": [10, 20, 30],
    "quantity":  [4, 5, 6]
})

t >>= {'total': t.price * t.quantity}
t >>= {'tax': t.total * 0.1}

t
# 'price ($)'   quantity   total      tax
#      .price  .quantity  .total     .tax
#       [int]      [int]   [int]  [float]
#          10          4      40      4.0
#          20          5     100     10.0
#          30          6     180     18.0
#
# 3×4 table <int:3, float>

Installation

pip install serif

Zero dependencies — pip freeze in a fresh environment shows exactly one line.

Quickstart

Vectors

from serif import Vector

a = Vector([1, 2, 3, 4, 5])

a * 2         # 2, 4, 6, 8, 10
a > 3         # False, False, False, True, True
a[a > 3]      # 4, 5 — boolean masks filter
a.sum()       # 15 — a plain Python int

Tables

from serif import Table

t = Table({
    "first name": ["ann", "bo", "cy"],
    "price ($)":  [10, 20, 30],
})

t.price * 2                    # names sanitize for dot access
t >>= {'total': t.price * 2}   # add a column
t[t.price > 15]                # masks filter rows

t._                            # what do I have again?
# .first_name   str   'first name'
# .price        int   'price ($)'
# .total        int

None means missing

Element-wise, unknown in is unknown out. Aggregates summarize what you know. And a verdict needs evidence — all()/any() over zero valid values raise rather than guess.

v = Vector([10, None, 30])

v + 1        # 11, None, 31
v > 15       # False, None, True
v.sum()      # 40
len(v)       # 3

Vector([None, None]).any()                 # raises SerifEmptyReductionError
Vector([None, None]).any(on_empty=False)   # False — you supplied the verdict

Joins and aggregation

customers = Table({'id': [1, 2, 3], 'name': ['Ann', 'Bo', 'Cy']})
scores    = Table({'id': [2, 3, 4], 'score': [85, 90, 95]})

customers.inner_join(scores, left_on='id', right_on='id')
# id, name, score — matched key columns are not duplicated

sales = Table({'customer': ['A', 'B', 'A'], 'amount': [100, 200, 150]})

sales.aggregate(
    groupby=sales.customer,
    aggregations={'total': sales.amount.sum, 'n': len},
)
# customer  total  n
#        A    250  2
#        B    200  1

CSV and Parquet

from serif import read_csv, read_parquet

t = read_csv("sales.csv")        # types inferred, headers sanitized for dot access
t.to_parquet("sales.parquet")    # ints, dates, and nulls arrive intact
u = read_parquet("sales.parquet")

Documentation

License

MIT

Contributing

See CONTRIBUTING.md and CODE_OF_CONDUCT.md.

Project details


Download files

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

Source Distribution

serif-0.1.8.tar.gz (142.4 kB view details)

Uploaded Source

Built Distribution

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

serif-0.1.8-py3-none-any.whl (85.4 kB view details)

Uploaded Python 3

File details

Details for the file serif-0.1.8.tar.gz.

File metadata

  • Download URL: serif-0.1.8.tar.gz
  • Upload date:
  • Size: 142.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for serif-0.1.8.tar.gz
Algorithm Hash digest
SHA256 d0905ee4926688525c6d64e2a5e1b5b54dd591f2cb89f1f09b28ad3c909daa42
MD5 a596043f9b98e6e707e7ef463ccc2017
BLAKE2b-256 0a9876b6695c8e34285577ed2e1cbb340f0fb62cdf68bd5ceb196e182e31c8d9

See more details on using hashes here.

File details

Details for the file serif-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: serif-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 85.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for serif-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 c60eab62f91e975b5f954721413d6d95d85fd3daf99f84ea103ba6f88ee14fb9
MD5 2efa4dc1e557bae17d2bcf18b5806abf
BLAKE2b-256 a06000eded1405c0f7c0cae9c91969d260cba1794fddb350fd047b266cf5264b

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 Pingdom Monitoring Sentry Error logging StatusPage Status page