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 <3×int, 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.7.tar.gz (142.0 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.7-py3-none-any.whl (85.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: serif-0.1.7.tar.gz
  • Upload date:
  • Size: 142.0 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.7.tar.gz
Algorithm Hash digest
SHA256 f289a8544e70ef74b5a8ead1e784d4aec1a5e269d70eab2776d502c8a4fa115f
MD5 66fcf11117f11111696aec99fc41d05d
BLAKE2b-256 72c30752f472e16cccef86a8d77328fd44bdc5be364e9f0ddbaefacdad3cc73b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: serif-0.1.7-py3-none-any.whl
  • Upload date:
  • Size: 85.3 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.7-py3-none-any.whl
Algorithm Hash digest
SHA256 388f69bb73b0a52dd396023157c7f3f947fd55009b63936fd637cb4bfa22c3d2
MD5 dc471b36fe1fc2142be8f068b4700974
BLAKE2b-256 f461d31db7d021ed6280ca0a5db56725c60a85a9ddceada09c94991f9c23941b

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