Skip to content

Commit 3acea8f

Browse files
add transform-tabular
1 parent 532aa03 commit 3acea8f

6 files changed

Lines changed: 1360 additions & 0 deletions

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: transform-tabular
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "packages/transform-tabular/**"
8+
pull_request:
9+
branches: [main]
10+
paths:
11+
- "packages/transform-tabular/**"
12+
13+
defaults:
14+
run:
15+
working-directory: packages/transform-tabular
16+
17+
jobs:
18+
test:
19+
runs-on: ${{ matrix.os }}
20+
strategy:
21+
matrix:
22+
os: [ubuntu-latest, macos-latest, windows-latest]
23+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
24+
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- name: Set up Python ${{ matrix.python-version }}
29+
uses: actions/setup-python@v5
30+
with:
31+
python-version: ${{ matrix.python-version }}
32+
33+
- name: Install dependencies
34+
run: |
35+
python -m pip install --upgrade pip
36+
pip install -e ".[test]"
37+
38+
- name: Run tests
39+
run: pytest tests/ -v
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# transform-tabular
2+
3+
[![Tests](https://github.com/Daniele-Gregori/PyPI-packages/actions/workflows/tests.yml/badge.svg)](https://github.com/Daniele-Gregori/PyPI-packages/actions/workflows/tests.yml)
4+
[![PyPI version](https://img.shields.io/pypi/v/transform-tabular)](https://pypi.org/project/transform-tabular/)
5+
[![Python versions](https://img.shields.io/pypi/pyversions/transform-tabular)](https://pypi.org/project/transform-tabular/)
6+
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7+
8+
9+
10+
Apply a single function element-wise across an entire DataFrame, or a selection of its columns.
11+
12+
Two special markers extend this to column-aware operations:
13+
14+
- **`ColumnwiseValue(func)`** — computes a scalar aggregate per column (e.g. mean, max). The scalar is then used in the element-wise expression, so every row in that column sees the same aggregate.
15+
- **`ColumnwiseThread(func)`** — applies a list-to-list transformation per column (e.g. sort, cumulative sum). Each row receives the corresponding element from the transformed list.
16+
17+
This package is a Python port of the Wolfram Language resource function [`TransformTabular`](https://resources.wolframcloud.com/FunctionRepository/resources/TransformTabular/).
18+
19+
20+
## Usage
21+
22+
```python
23+
from transform_tabular import transform_tabular, ColumnwiseValue, ColumnwiseThread
24+
import pandas as pd
25+
```
26+
27+
### Syntax
28+
29+
```python
30+
transform_tabular(df, func) # apply func element-wise to all columns
31+
transform_tabular(df, func, columns) # apply func only to selected columns
32+
transform_tabular(func) # operator form: returns a reusable transformer
33+
transform_tabular(func, columns) # operator form with column selection
34+
```
35+
36+
**Parameters**
37+
38+
| Parameter | Type | Description |
39+
|-----------|------|-------------|
40+
| `df` | `DataFrame` | Input DataFrame |
41+
| `func` | callable | Function applied element-wise to each cell. May reference `ColumnwiseValue` / `ColumnwiseThread` markers. |
42+
| `columns` | optional | Column selection: a name (`str`), index (`int`), list of names/indices, or `slice`. Defaults to all columns. |
43+
44+
The function `func` is applied element-wise. The optional third argument can be either a list of columns, a list of column indices, a single column, or a slice.
45+
46+
### Basic transformation
47+
48+
Increment all numeric columns by 1:
49+
50+
```python
51+
df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
52+
transform_tabular(df, lambda x: x + 1)
53+
# a b
54+
# 0 2 5
55+
# 1 3 6
56+
# 2 4 7
57+
```
58+
59+
### Column selection
60+
61+
Transform only specific columns:
62+
63+
```python
64+
df = pd.DataFrame({"a": [1, 2, 3], "b": [10, 20, 30], "c": [100, 200, 300]})
65+
transform_tabular(df, lambda x: x * 2, ["a", "c"])
66+
# a b c
67+
# 0 2 10 200
68+
# 1 4 20 400
69+
# 2 6 30 600
70+
```
71+
72+
### ColumnwiseValue (column-level aggregation)
73+
74+
`ColumnwiseValue(func)` wraps a function `func(column_as_list) -> scalar`. The scalar is pre-computed per column and then participates in the element-wise arithmetic — every row in a given column sees that column's aggregate.
75+
76+
Subtract the mean from each element (centering):
77+
78+
```python
79+
df = pd.DataFrame({"x": [1, 2, 3, 4, 5], "y": [10, 20, 30, 40, 50]})
80+
cv_mean = ColumnwiseValue(lambda col: sum(col) / len(col))
81+
transform_tabular(df, lambda x: x - cv_mean)
82+
# x y
83+
# 0 -2.0 -20.0
84+
# 1 -1.0 -10.0
85+
# 2 0.0 0.0
86+
# 3 1.0 10.0
87+
# 4 2.0 20.0
88+
```
89+
90+
### ColumnwiseThread (column-level transformation)
91+
92+
`ColumnwiseThread(func)` wraps a function `func(column_as_list) -> list_of_same_length`. The transformation is pre-computed per column and each row receives its corresponding element from the resulting list.
93+
94+
Sort each column independently:
95+
96+
```python
97+
df = pd.DataFrame({"a": [3, 1, 2], "b": [6, 4, 5]})
98+
ct_sorted = ColumnwiseThread(lambda col: sorted(col))
99+
transform_tabular(df, lambda x: ct_sorted)
100+
# a b
101+
# 0 1 4
102+
# 1 2 5
103+
# 2 3 6
104+
```
105+
106+
### Combined ColumnwiseValue and ColumnwiseThread
107+
108+
Both markers can be used together. For example, sort each column and then add its mean:
109+
110+
```python
111+
df = pd.DataFrame({"a": [3, 1, 2], "b": [60, 40, 50]})
112+
ct_sorted = ColumnwiseThread(lambda col: sorted(col))
113+
cv_mean = ColumnwiseValue(lambda col: sum(col) / len(col))
114+
transform_tabular(df, lambda x: ct_sorted + cv_mean)
115+
# a b
116+
# 0 3.0 90.0
117+
# 1 4.0 100.0
118+
# 2 5.0 110.0
119+
```
120+
121+
### Operator form
122+
123+
`transform_tabular` can be curried to produce a reusable transformer:
124+
125+
```python
126+
double_all = transform_tabular(lambda x: x * 2)
127+
double_all(pd.DataFrame({"a": [1, 2], "b": [3, 4]}))
128+
# a b
129+
# 0 2 6
130+
# 1 4 8
131+
```
132+
133+
## See also
134+
135+
For further details and examples, see the documentation for the original Wolfram Language resource function: [TransformTabular](https://resources.wolframcloud.com/FunctionRepository/resources/TransformTabular/).
136+
137+
## Author
138+
139+
Daniele Gregori
140+
141+
## License
142+
143+
MIT
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[build-system]
2+
requires = ["setuptools>=61.0"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "transform-tabular"
7+
version = "0.8.0"
8+
description = "Transform columns of pandas DataFrames with element-wise, column-aggregate, and column-threaded operations"
9+
authors = [{name = "Daniele Gregori"}]
10+
requires-python = ">=3.9"
11+
license = {text = "MIT"}
12+
readme = "README.md"
13+
dependencies = ["pandas>=1.3.0"]
14+
classifiers = [
15+
"Development Status :: 4 - Beta",
16+
"Intended Audience :: Developers",
17+
"Intended Audience :: Science/Research",
18+
"License :: OSI Approved :: MIT License",
19+
"Programming Language :: Python :: 3",
20+
"Programming Language :: Python :: 3.9",
21+
"Programming Language :: Python :: 3.10",
22+
"Programming Language :: Python :: 3.11",
23+
"Programming Language :: Python :: 3.12",
24+
"Programming Language :: Python :: 3.13",
25+
"Topic :: Scientific/Engineering",
26+
]
27+
28+
[project.urls]
29+
Homepage = "https://github.com/Daniele-Gregori/PyPI-packages/tree/main/packages/transform-tabular"
30+
Repository = "https://github.com/Daniele-Gregori/PyPI-packages"
31+
Issues = "https://github.com/Daniele-Gregori/PyPI-packages/issues"
32+
Documentation = "https://resources.wolframcloud.com/FunctionRepository/resources/TransformTabular/"
33+
34+
[project.optional-dependencies]
35+
test = ["pytest>=7.0"]
36+
37+
[tool.setuptools.packages.find]
38+
where = ["src"]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""transform_tabular: Transform columns of pandas DataFrames.
2+
3+
Python translation of the Wolfram Language ResourceFunction TransformTabular.
4+
Provides element-wise, column-aggregate (ColumnwiseValue), and column-threaded
5+
(ColumnwiseThread) operations on DataFrame columns.
6+
"""
7+
8+
__version__ = "0.8.0"
9+
10+
from .core import (
11+
ColumnwiseValue,
12+
ColumnwiseThread,
13+
transform_tabular,
14+
)
15+
16+
__all__ = [
17+
"ColumnwiseValue",
18+
"ColumnwiseThread",
19+
"transform_tabular",
20+
]

0 commit comments

Comments
 (0)