Skip to content

Commit 1363a6b

Browse files
committed
final docs clean up
1 parent 7c06abf commit 1363a6b

3 files changed

Lines changed: 86 additions & 142 deletions

File tree

.github/workflows/docs.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Deploy Docs
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
deploy:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Configure Git Credentials
17+
run: |
18+
git config user.name "github-actions[bot]"
19+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
20+
21+
- uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.x"
24+
25+
- name: Cache MkDocs build
26+
uses: actions/cache@v4
27+
with:
28+
key: mkdocs-material-${{ github.sha }}
29+
path: .cache
30+
restore-keys: |
31+
mkdocs-material-
32+
33+
- name: Install docs dependencies
34+
run: pip install mkdocs-material
35+
36+
- name: Build and deploy to gh-pages
37+
run: mkdocs gh-deploy --force

README.md

Lines changed: 37 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,186 +1,84 @@
11
# Percentify
22

3-
[![Downloads](https://static.pepy.tech/badge/percentify)](https://pepy.tech/project/percentify )
3+
[![Downloads](https://static.pepy.tech/badge/percentify)](https://pepy.tech/project/percentify)
44
[![PyPI version](https://img.shields.io/pypi/v/percentify.svg?style=flat&color=blue)](https://pypi.org/project/percentify/)
55
[![Python Versions](https://img.shields.io/pypi/pyversions/percentify.svg?style=flat&color=green)](https://pypi.org/project/percentify/)
66
[![License](https://img.shields.io/pypi/l/percentify.svg?style=flat&color=orange)](LICENSE)
7+
[![Docs](https://img.shields.io/badge/docs-percentify-14b8a6)](https://data-centt.github.io/percentify/)
78
[![Build Status](https://github.com/data-centt/percentify/actions/workflows/python-app.yml/badge.svg)](https://github.com/data-centt/percentify/actions/workflows/python-app.yml)
89

910
**Percentify is a niche data science library for practitioners and learners alike, drawing its main dependencies from pandas and numpy, and including everyday statistics.**
1011

11-
Following the **Pareto principle**, Percentify brings the 20% of operations that make up 80% of daily data work to the forefront, each as a single, readable function call. No more digging through six-line recipes and hard-to-remember import paths for the checks you run on every dataset.
12+
Following the **Pareto principle**, Percentify brings the 20% of operations that make up 80% of daily data work to the forefronteach as a single, readable function call. It does not aim to compete with pandas, scipy, statsmodels, or scikit-learn; it stands on their shoulders and works alongside them, naming the library each function draws from so you always know where to dig deeper.
1213

13-
Percentify **does not aim to compete** with pandas, scipy, statsmodels, or scikit-learn; it stands on their shoulders and works *alongside* them. The goal is to make the core concepts easy to learn, quick to use, and simple to remember. Every function names the underlying library it draws from, so the moment you need the full, configurable version, you know exactly where to go.
14+
## 📖 Documentation
1415

15-
Every function takes a pandas `DataFrame` (or `Series`) and hands back a clean `DataFrame` you can read, sort, or feed straight into the next step.
16-
17-
---
16+
**Full guide, every function, and live examples → [data-centt.github.io/percentify](https://data-centt.github.io/percentify/)**
1817

1918
## 📦 Installation
20-
```
19+
20+
```bash
2121
pip install percentify
2222
```
2323

2424
Requires `numpy` and `pandas`.
2525

26-
---
27-
28-
## 📊 The Toolkit
29-
30-
### `change`: Percentage Change
31-
Two numbers, two columns, or a whole series at once.
32-
```python
33-
from percentify import change
34-
35-
change(100, 150) # → 50.0 (a 50% increase)
26+
## Quick example
3627

37-
change(df["forecast"], df["actual"]) # element-wise % change between two columns
38-
39-
change(df["revenue"]) # period-over-period % change down the column
40-
# 0 NaN
41-
# 1 50.0
42-
# 2 -40.0
43-
44-
change(df) # every numeric column at once
45-
```
46-
47-
### `vif`: Variance Inflation Factor (Multicollinearity)
48-
The classic multicollinearity check, without the six-line loop.
49-
> _Similar Concept:_ `statsmodels.stats.outliers_influence.variance_inflation_factor`
50-
```python
51-
from percentify import vif
52-
53-
vif(df)
54-
# feature VIF
55-
# 0 income 8.40
56-
# 1 debt 7.90
57-
# 2 age 1.20
58-
59-
vif(df, flag=5.0) # only rows above the threshold (your problem columns)
60-
```
61-
62-
### `missing`: Missing Data Profiling
63-
No more `df.isnull().sum() / len(df) * 100`.
64-
> _Underlying library:_ `pandas.DataFrame.isna`
6528
```python
29+
import pandas as pd
6630
from percentify import missing
6731

32+
df = pd.DataFrame({
33+
"salary": [50000, None, 60000, None],
34+
"age": [25, 30, None, 40],
35+
"city": ["NY", "LA", "SF", "LA"],
36+
})
37+
6838
missing(df)
6939
# column missing_pct
70-
# 0 salary 12.40
71-
# 1 age 3.10
72-
# 2 name 0.00
40+
# 0 salary 50.0
41+
# 1 age 25.0
42+
# 2 city 0.0
7343
```
7444

75-
### `cv`: Coefficient of Variation
76-
Relative variability (std ÷ mean), as a percentage.
77-
> _Underlying library:_ `scipy.stats.variation`
78-
```python
79-
from percentify import cv
45+
One import, one line — a clean, sorted DataFrame you can read or feed into the next step.
8046

81-
cv(df["salary"]) # → 34.2 (a single Series returns a number)
82-
cv(df) # → DataFrame of every numeric column, most variable first
83-
```
47+
## What's inside
8448

85-
### `outliers`: Percentage of Outliers (IQR Method)
86-
Stop rewriting the IQR bounds from scratch.
87-
> _Similar Concept:_ `scipy.stats.iqr`
88-
```python
89-
from percentify import outliers
49+
| Function | What it answers |
50+
|---|---|
51+
| `change` | Growth — as numbers, columns, or a whole series |
52+
| `vif` | Which features are collinear? |
53+
| `missing` | How much of each column is missing? |
54+
| `cv` | How variable is each column, relative to its mean? |
55+
| `outliers` | What percentage of each column are outliers? |
56+
| `r_squared` | How well do predictions fit? |
57+
| `pca_variance` | How much variance does each principal component explain? |
58+
| `difference` | How far apart are two values or columns? |
59+
| `split` | How does a total divide across weights or groups? |
60+
| `display` | Format numbers or a column as clean "%" strings |
9061

91-
outliers(df["salary"]) # → 4.7
92-
outliers(df) # → DataFrame of every numeric column
93-
```
94-
95-
### `r_squared`: R-Squared
96-
```python
97-
from percentify import r_squared
98-
99-
r_squared(y_true, y_pred) # → 87.3
100-
```
101-
> _Similar Concepts:_ `sklearn.metrics.r2_score`
102-
103-
### `pca_variance`: PCA Variance Breakdown
104-
Columns are standardized by default, so a feature measured in large units (e.g.
105-
dollars) can't dominate the result just because of its scale. Pass
106-
`standardize=False` for covariance-based PCA on the raw values.
107-
> _Similar Concept:_ `sklearn.decomposition.PCA` (`.explained_variance_ratio_`)
108-
```python
109-
from percentify import pca_variance
110-
111-
pca_variance(df)
112-
# component variance_explained cumulative
113-
# 0 PC1 45.2 45.2
114-
# 1 PC2 23.1 68.3
115-
# 2 PC3 12.8 81.1
116-
117-
pca_variance(df, standardize=False) # covariance-based (scale-sensitive)
118-
```
119-
120-
### `difference`: Symmetric % Difference
121-
How far apart two values or columns are, regardless of direction (use `change` when direction matters).
122-
> _Similar Concept:_ `numpy` / `pandas` arithmetic
123-
```python
124-
from percentify import difference
125-
126-
difference(10, 20) # → 66.67 (order-independent)
127-
128-
difference(df["sensor_a"], df["sensor_b"]) # element-wise % gap between two columns
129-
```
130-
131-
### `split`: Proportional Allocation
132-
Distribute a total across weights or groups.
133-
> _Similar Concept:_ `numpy` / `pandas` arithmetic
134-
```python
135-
from percentify import split
136-
137-
split(10000, [2, 3, 5]) # → [2000.0, 3000.0, 5000.0]
138-
139-
split(10000, df["population"]) # allocate a budget by population (aligned Series)
140-
```
141-
142-
### `display`: Percentage Formatting
143-
Turn numbers or a whole column into clean "%" strings for reports.
144-
> _Similar Concept:_ `pandas.Series.map` + string formatting
145-
```python
146-
from percentify import display
147-
148-
display(0.45, multiply=True) # → "45.0%"
149-
150-
display(df["conv_rate"], multiply=True) # → column of "4.5%" strings
151-
```
152-
153-
---
62+
→ See the **[documentation](https://data-centt.github.io/percentify/)** for a worked, real-output example of every function.
15463

15564
## 🛟 Friendly by design
15665

157-
Built for early-career analysts as much as seasoned ones:
158-
159-
- **No cryptic tracebacks.** Hand it a text column where numbers are needed and you get a clear `PercentifyWarning` ("numeric columns required") plus an empty result — not an Arrow/NumPy stack trace.
160-
- **Sensible defaults.** Results come back sorted worst-first (most collinear, most missing, most variable), and PCA is standardized out of the box.
66+
- **No cryptic tracebacks.** Hand a function a text column where numbers are needed and you get a clear `PercentifyWarning`, not an Arrow/NumPy stack trace.
67+
- **Sensible defaults.** Results come back sorted worst-first, and PCA is standardized out of the box.
16168
- **DataFrames everywhere**, so the output drops straight into your notebook, your next filter, or your model.
16269

163-
Catch or silence the warnings like any other:
164-
```python
165-
import warnings
166-
from percentify import PercentifyWarning
167-
168-
warnings.filterwarnings("ignore", category=PercentifyWarning)
169-
```
170-
171-
---
172-
17370
## 🤝 Contributing
17471

17572
Contributions are welcome — but they must follow the repo's guiding principle:
17673

17774
> **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.
17875
17976
If your idea keeps things that simple and direct:
77+
18078
- Open an issue first to discuss it
18179
- Fork the repo
18280
- Create a branch
18381
- Commit your changes
18482
- Open a pull request
18583

186-
> Anything that adds knobs and options for their own sake, or duplicates what the parent libraries already do well, is out of scope please those cases should point to the source library instead.
84+
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.

percentify/stats.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,9 @@ def cv(data: Union[pd.Series, pd.DataFrame], decimals: Optional[int] = 2) -> Uni
224224
return result.sort_values("cv", ascending=False).reset_index(drop=True)
225225

226226

227-
def outliers(data: Union[pd.Series, pd.DataFrame], decimals: Optional[int] = 2, multiplier: float = 1.5) -> Union[float, pd.DataFrame]:
227+
def outliers(
228+
data: Union[pd.Series, pd.DataFrame], decimals: Optional[int] = 2, multiplier: float = 1.5
229+
) -> Union[float, pd.DataFrame]:
228230
"""
229231
Calculate the percentage of outliers using the IQR method.
230232
@@ -272,7 +274,11 @@ def _calc(s: pd.Series) -> float:
272274
return result.sort_values("outlier_pct", ascending=False).reset_index(drop=True)
273275

274276

275-
def r_squared(y_true: Union[pd.Series, Sequence, np.ndarray], y_pred: Union[pd.Series, Sequence, np.ndarray], decimals: Optional[int] = 2) -> float:
277+
def r_squared(
278+
y_true: Union[pd.Series, Sequence, np.ndarray],
279+
y_pred: Union[pd.Series, Sequence, np.ndarray],
280+
decimals: Optional[int] = 2,
281+
) -> float:
276282
"""
277283
Calculate R-squared (coefficient of determination).
278284
@@ -311,7 +317,10 @@ def r_squared(y_true: Union[pd.Series, Sequence, np.ndarray], y_pred: Union[pd.S
311317
return _round(val, decimals)
312318

313319

314-
def pca_variance(df: pd.DataFrame, decimals: Optional[int] = 2, n_components: Optional[int] = None, standardize: bool = True) -> pd.DataFrame:
320+
def pca_variance(
321+
df: pd.DataFrame, decimals: Optional[int] = 2, n_components: Optional[int] = None,
322+
standardize: bool = True,
323+
) -> pd.DataFrame:
315324
"""
316325
Calculate the percentage of variance explained by each principal component.
317326

0 commit comments

Comments
 (0)