Imported from lucidfrontier45/polars-tsfresh (
AGENTS.md). Install upstream withnpx skills add lucidfrontier45/polars-tsfresh. Copyright stays with the author.
AGENTS.md
This document provides essential information for coding agents working on the polars-tsfresh project.
Build, Lint, and Test Commands
This project is managed with uv. Always use uv to invoke Python and related tools.
Full Quality Check
uv run poe check
Runs both linting (ruff) and type checking (pyrefly) in sequence.
Testing
Invoke pytest with uv.
Code Style Guidelines
Function Signatures and Type Hints
- Use comprehensive type hints for all parameters and return values
- Use
pl.Exprfor Polars expressions - Use
list[pl.Expr]for collections of expressions
def extract_features(df: pl.DataFrame, column_id: str, column_sort: str) -> pl.DataFrame:
"""Extract features from a Polars DataFrame using tsfresh-like functionality.
Parameters:
df (pl.DataFrame): Input Polars DataFrame.
column_id (str): The name of the column containing the IDs.
column_sort (str): The name of the column to sort by.
Returns:
pl.DataFrame: DataFrame with extracted features.
"""
Documentation
- Use Google-style docstrings with
Args:andReturns:sections - Document all parameters with types and descriptions
- Document return values with types and descriptions
- Include brief function description
Polars Patterns
- Use pure Polars expressions as far as possible — implement features with native
pl.Exproperations only. Fall back to other approaches (map_batches, numpy, Python UDFs) only when absolutely necessary, e.g. no native equivalent exists. Pure expressions run in Rust, stay visible to the query optimizer, and avoid per-group Python overhead (measured ~16x faster for grouped feature extraction). - Use method chaining when possible
- Use
.alias()for column naming withcolumn_name__feature_namepattern - Prefer expressions over direct column operations
- Use aggregation context for grouped operations
# Good: Expression-based approach
return pl.col(col_name).mean().alias(f"{col_name}__mean")
# Good: Method chaining
grouped = df.sort(column_sort).group_by(column_id)
result = grouped.agg(feature_exprs)
Error Handling
- Use descriptive assertion messages in tests
- Avoid bare exceptions - provide context
- Test floating-point comparisons with tolerance functions
def float_close(a: float, b: float, tol=1e-5) -> bool:
return abs(a - b) < tol
assert float_close(val, val_true), f"Feature {col} does not match: {val} != {val_true}"
Testing Patterns
- Test files in
tests/directory - Use descriptive test function names (e.g.,
test_minimal) - Load test data from
tests/data/directory - Use Path objects for file operations
- Compare floating-point values with tolerance
- Skip irrelevant columns in assertions
def test_minimal():
x_csv_path = Path(__file__).parent.parent / "data" / "sp500_raw.csv"
y_csv_path = Path(__file__).parent.parent / "data" / "sp500_tsfresh_features.csv"
df = pl.read_csv(x_csv_path).with_columns(pl.lit("sp500").alias("kind"))
features = extract_features(df, column_id="kind", column_sort="date")
features_true = pl.read_csv(y_csv_path)
# ... assertions
Development Workflow
- Make changes to source code
- Run
uv run poe checkto verify quality - Run
uv run poe testto ensure tests pass
Project-Specific Notes
- This is a Polars-based reimplementation of tsfresh feature extraction
- Focus on performance and type safety
- Minimal feature set currently includes basic statistical measures
- Uses double underscore (
__) separator in feature column names - Designed for time series data grouped by ID columns AGENTS.md