Skip to content

williambdean/frame-search

Repository files navigation

Frame Search

Ruff Tests PyPI version

A GitHub search inspired interface to DataFrames.

Powered by narwhals.

Installation

Install from PyPI:

uv add frame-search

Usage

API

Importing frame_search adds a search properties to pandas and polars objects.

# Import to add `search` property to DataFrames
import frame_search  # noqa: F401

import polars as pl

df = pl.DataFrame({
    "name": ["Alice Smith", "Bob J. Dawkins", "Charlie Brown"],
    "age": [25, 30, 35],
    "hometown": ["New York", "New York", "Chicago"]
})

df.search('age:<30 hometown:"New York"')
shape: (1, 3)
┌─────────────┬─────┬──────────┐
│ name        ┆ age ┆ hometown │
│ ---         ┆ --- ┆ ---      │
│ str         ┆ i64 ┆ str      │
╞═════════════╪═════╪══════════╡
│ Alice Smith ┆ 25  ┆ New York │
└─────────────┴─────┴──────────┘

Interactive Search in Marimo Notebooks

Use with marimo to create a search interface for DataFrames:

import marimo as mo

search = mo.ui.text(label="DataFrame Search Query:")
search

Then use on a DataFrame:

import polars as pl

import frame_search  # noqa: F401

df = pl.DataFrame({
    "name": ["Alice Smith", "Bob J. Dawkins", "Charlie Brown"],
    "age": [25, 30, 35],
    "hometown": ["New York", "Los Angeles", "Chicago"]
})

df_filter = df.search(search.value)

df_filter

Here is another example in a Marimo notebook:

Marimo Example

Features

Syntax Description Example
key:value Case-insensitive substring match name:alice
key:value1,value2 Match any of the values (isin) hobby:Reading,Sports
key:low..high Range match (inclusive) age:20..40
key:>value Comparator (<, <=, >, >=, ==, !=) age:>30
"quoted value" Exact string with spaces city:"New York"
is:col Boolean column is True is:active
has:col Column is not null has:nickname
no:col Column is null no:nickname
term1 term2 Implicit AND (space-separated) name:alice age:>20
term1 AND term2 / term1 & term2 Explicit AND name:alice AND age:>20
term1 OR term2 / term1 | term2 OR operator hobby:Reading OR hobby:Sports
NOT term / -term / ~term Negation -name:alice, NOT age:>30
(expr) Grouping with parentheses (name:alice OR name:bob) AND age:>20
`col name`:value Backtick-quoted column with spaces `first name`:alice

Search Expression Grammar

This repository defines a small, expressive query language for filtering and searching structured data. The grammar is implemented in Lark and supports boolean logic, comparisons, ranges, set membership, dates, numbers, strings, and quoted identifiers.

The language is designed to be:

  • Readable for humans
  • Unambiguous for the parser
  • Flexible enough to express common filtering patterns

Syntax Overview

A query is an expression composed of:

  • Boolean operators: AND, OR, NOT (with symbolic aliases &, |, ~)
  • Comparisons between a key and a value
  • Range expressions (..)
  • Set membership (value,value,...)
  • Parentheses for grouping

At a high level:

<key> <comparator> <search_rhs>

Where a key identifies the field being queried. A comparator represents an operator that compares two sides (e.g. <, >, ==). search_rhs can take on many different values including dates/datetimes, integers/floats, booleans, strings, and other columns.

Keys

Keys identify the field being queried, and are always inferred to exist on the left side of any comparison. To refer to column names that have spaces in them, one needs to surround the name in backticks.

name:Alice         # queries the name column for the string Alice
`first name`:Alice # queries the `first name` column for the string Alice
`first.name`:Alice # queries the `first.name` column for the string Alice

In the above example, both "first name" and "first.name" must be surrounded in backticks.

Comparators

Operator Meaning
== equality
!= inequality
< less than
<= less than or equal
> greater than
>= greater than or equal
: value dependent

The : operator is special in that it allows for a flexible supset of expressions to be parsed and used

  • str: name:Alice queries the name column for any value that starts with Alice or alice (case-insensitive prefix matching)
  • isin: name:Alice,Bob queries the name column for either Alice or Bob (same as case-insensitive prefix matching for strings)
  • range: age:20..40 queries the age column for any value between 20 and 40 (inclusive)

About

A GitHub search inspired interface to DataFrames

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors