Skip to content

Commit c462f0b

Browse files
Merge pull request #1 from data-centt/main
compare
2 parents abcd940 + ee80d5b commit c462f0b

2 files changed

Lines changed: 160 additions & 5 deletions

File tree

CONTRIBUTING.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Contributing to Percentify
2+
3+
Thank you for your interest in contributing to Percentify! We welcome contributions, but ask that you follow the project's guiding principles to keep the library focused and simple.
4+
5+
## Guiding Principles
6+
7+
Percentify is built on the idea of simplicity and directness.
8+
9+
> Keep each method as direct-to-output as possible. A percentify function should return the single most common answer in one line, and point users to the underlying library (pandas, scipy, statsmodels, scikit-learn) for the full, configurable version when the simplest output isn't what they're after.
10+
11+
- **No unnecessary knobs and options**: Anything that adds parameters for their own sake, or duplicates what the parent libraries already do well, is out of scope. For those cases, users should be pointed to the source library instead.
12+
- **Keep it compact**: We try to keep the API surface compact on purpose. Please discuss big new features in an issue before writing code.
13+
14+
## Technical Requirements
15+
16+
**It must support Polars.**
17+
Every function in Percentify accepts both pandas and Polars objects (via the `@_backend_aware` decorator) and returns the same kind. Any new contribution must maintain this parity. You should not require the user to manually convert between backends or pass specific flags.
18+
19+
## Contribution Workflow
20+
21+
If your idea keeps things simple, direct, and adheres to the principles above, here is how you can contribute:
22+
23+
1. **Discuss first**: Open an issue to discuss your proposed change or feature. This saves time and ensures your contribution aligns with the project's goals.
24+
2. **Fork and Branch**: Fork the repository and create a new branch for your feature or bugfix.
25+
3. **Develop**: Write your code, ensuring it supports both pandas and Polars.
26+
4. **Test**: (Include any testing guidelines if applicable, e.g., using `pytest`).
27+
5. **Commit and Push**: Commit your changes with clear, descriptive commit messages.
28+
6. **Pull Request**: Open a pull request against the main branch. Reference the issue you opened in step 1.
29+
30+
We look forward to reviewing your contributions!

README.md

Lines changed: 130 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
<p align="center">
32
<img src="https://raw.githubusercontent.com/data-centt/percentify/main/asset/log.png" alt="Percentify logo" height="140">
43
</p>
@@ -19,7 +18,7 @@ Exploratory stats and data-quality diagnostics for pandas and **Polars** DataFra
1918
2019
Where a function wraps an existing library (pandas, scipy, statsmodels, scikit-learn), it names it, so you always know where to dig deeper.
2120

22-
## The flagship: `profiler`
21+
## `profiler`
2322

2423
**pandas `.describe()` tells you what your data _is_. `profiler()` tells you what to _do_ about it:** every issue ranked worst-first, each with its fix.
2524

@@ -48,6 +47,17 @@ pip install percentify
4847

4948
Requires Python 3.10+, `numpy`, and `pandas` 2.0+.
5049

50+
## How to use percentify
51+
52+
Import the function that matches the question you want to answer, pass in a pandas or Polars object, and use the returned DataFrame or scalar directly in your notebook, report, or pipeline.
53+
54+
```python
55+
from percentify import missing, profiler
56+
57+
missing(df) # quick column-level check
58+
profiler(df, target="churn") # ranked data-quality issues and fixes
59+
```
60+
5161
## Quick example
5262

5363
```python
@@ -69,6 +79,124 @@ missing(df)
6979

7080
One import, one line. A clean, sorted DataFrame you can read or feed into the next step.
7181

82+
## Examples
83+
84+
These are short, recipe-style examples that go beyond the one-liner above and are intentionally not covered in the [documentation](https://data-centt.github.io/percentify/documentation/). The docs show each function in isolation; these show how to chain them into a real workflow.
85+
86+
### A 30-second data-quality gate
87+
88+
Drop this into CI to block training on a dataset that isn't ready:
89+
90+
```python
91+
import pandas as pd
92+
from percentify import profiler
93+
94+
df = pd.read_parquet("train.parquet")
95+
report = profiler(df, target="label")
96+
97+
assert report.errors.empty, report.to_frame()
98+
assert report.health >= 80, f"health too low: {report.health}"
99+
```
100+
101+
### Rank correlations by significance
102+
103+
Pull the pairs that are both strong *and* unlikely to be noise:
104+
105+
```python
106+
import pandas as pd
107+
from percentify import correlate
108+
109+
df = pd.DataFrame({
110+
"x": range(50),
111+
"y": [v * 0.9 + (v % 3) for v in range(50)],
112+
"z": [v * 0.05 for v in range(50)],
113+
"w": [v % 7 for v in range(50)],
114+
})
115+
116+
print(correlate(df).sort_values("p_value").head(5))
117+
```
118+
119+
### Build a transform pipeline from `skew_report`
120+
121+
Let `skew_report` tell you what to apply, then apply it:
122+
123+
```python
124+
import numpy as np
125+
import pandas as pd
126+
from percentify import skew_report
127+
128+
df = pd.DataFrame({
129+
"income": [30_000, 35_000, 1_200_000, 40_000, 28_000],
130+
"visits": [1, 1, 1, 50, 2],
131+
})
132+
133+
plan = skew_report(df)
134+
print(plan[["feature", "skew", "suggested_transform"]])
135+
# feature skew suggested_transform
136+
# 0 income 2.27 log1p
137+
# 1 visits 2.19 log1p
138+
139+
df["income_log"] = np.log1p(df["income"]) # numpy / pandas, not percentify
140+
df["visits_log"] = np.log1p(df["visits"])
141+
```
142+
143+
### Interpret PCA with both calls
144+
145+
Variance tells you *how much* of the signal each axis carries; loadings tell you *what it means*:
146+
147+
```python
148+
import pandas as pd
149+
from percentify import pca_variance, pca_loadings
150+
151+
df = pd.DataFrame({
152+
"height_cm": [160, 170, 180, 175, 165],
153+
"weight_kg": [55, 68, 82, 74, 60],
154+
"age": [25, 35, 45, 30, 28],
155+
})
156+
157+
print(pca_variance(df)) # PC1 carries most of the variance
158+
print(pca_loadings(df)) # PC1 = (height, weight) with similar signs
159+
```
160+
161+
### Drop collinear columns before modelling
162+
163+
Use `vif` with a threshold to get a drop-list you can feed straight into `df.drop`:
164+
165+
```python
166+
import pandas as pd
167+
from percentify import vif
168+
169+
df = pd.DataFrame({
170+
"price": [10, 12, 11, 13, 9, 14, 8, 12],
171+
"cost": [ 6, 7, 7, 8, 5, 8, 4, 7], # tracks price
172+
"margin": [ 4, 5, 4, 5, 4, 6, 4, 5], # = price - cost
173+
"stock": [100, 80, 90, 70, 110, 60, 120, 85],
174+
})
175+
176+
to_drop = vif(df, flag=5.0)["feature"].tolist()
177+
print(to_drop) # e.g. ['cost', 'margin']
178+
clean = df.drop(columns=to_drop)
179+
```
180+
181+
### Month-over-month KPI table
182+
183+
`change` over a DataFrame applies period-over-period growth to every numeric column at once:
184+
185+
```python
186+
import pandas as pd
187+
from percentify import change
188+
189+
kpis = pd.DataFrame({
190+
"revenue": [100, 120, 150, 135, 180],
191+
"signups": [400, 420, 470, 460, 510],
192+
}, index=["Jan", "Feb", "Mar", "Apr", "May"])
193+
194+
print(change(kpis))
195+
```
196+
197+
- [Worked examples for every function](https://data-centt.github.io/percentify/documentation/)
198+
- [Project documentation](https://data-centt.github.io/percentify/)
199+
72200
## What's inside
73201

74202
| Function | What it answers |
@@ -114,6 +242,3 @@ If your idea keeps things that simple and direct:
114242
- Create a branch
115243
- Commit your changes
116244
- Open a pull request
117-
118-
> Anything that adds knobs and options for their own sake, or duplicates what the parent libraries already do well, is out of scope; those cases should point to the source library instead.
119-
I try to keep it compact on purpose, to discuss big new features first.

0 commit comments

Comments
 (0)