PhilanthroPy: Code for a cause—predictive analytics for advancement teams.
🚀 View the Full Documentation Site
What is PhilanthroPy?
PhilanthroPy is a Python library that slots directly into sklearn.pipeline.Pipeline. It covers the full predictive workflow for nonprofit and academic medical center (AMC) fundraising — from raw CRM cleaning and wealth imputation to major-gift propensity scoring, lapse prediction, and planned-giving intent.
Who it's for
One toolkit, two audiences:
- General nonprofit & university advancement teams (no PHI in scope) — CRM cleaning, RFM segmentation, wealth-screening imputation, and donor-propensity / lapse / planned-giving scoring. Start with
CRMCleaner,RFMTransformer,WealthScreeningImputer, andDonorPropensityModel. - Academic medical center (AMC) foundations running grateful-patient programs (PHI in scope, higher scrutiny) — clinical-encounter featurization via
EncounterTransformer,GratefulPatientFeaturizer, andDischargeToSolicitationWindowTransformer. Before production use, read Compliance Considerations: the PII handling here is a name-based heuristic, not formal HIPAA de-identification.
Maturity
Single-maintainer MIT project at v0.6.0 (Beta). Preprocessing and the core classifiers are stable; grateful-patient featurization and philanthropy.ingest are Beta; FinancialForecastModel and philanthropy.experimental.* are Experimental and carry no API guarantees. Per-symbol stability tiers are in the API reference.
Maintenance: maintained by one person on a best-effort basis. For vendor / OSS risk reviews: the bus factor is 1. Issues and PRs are welcome.
Installation
pip install philanthropy
From source (for development)
git clone https://github.com/PhilanthroPy-Project/PhilanthroPy.git
cd PhilanthroPy
pip install -e ".[dev]"
Quick Start
from philanthropy.datasets import generate_synthetic_donor_data
from philanthropy.models import DonorPropensityModel
df = generate_synthetic_donor_data(n_samples=500, random_state=42)
X = df[["total_gift_amount", "years_active", "event_attendance_count"]].to_numpy()
y = df["is_major_donor"].to_numpy()
model = DonorPropensityModel(n_estimators=200, random_state=0)
model.fit(X, y)
scores = model.predict_affinity_score(X) # 0–100 affinity scale
assert scores.shape == (500,)
assert len(set(scores.round(6))) > 1 # a constant score means a broken pipeline
Runnable scripts:
examples/quickstart.pyandexamples/unischema_to_scores.pyrun end to end and are smoke-tested in CI.
Output of plot_affinity_distribution(): the 0–100 affinity scores cleanly separate major from non-major donors.
From UniSchema events to scores
PhilanthroPy is the modeling half of an ecosystem. UniSchema normalizes fragmented advancement webhooks (GiveCampus, Slate, NPSP, Cvent, …) into a single ConstituentEvent stream. philanthropy.ingest turns that stream into the donor-level feature table the estimators expect — no glue code between the two projects.
Webhooks → UniSchema egress → read_constituent_events() → constituent_events_to_features() → predict_affinity_score(). Worked, runnable version with the full diagram: Ingest UniSchema events.
Feature overview
Full parameter documentation for every symbol below is rendered in the API reference.
🧹 Preprocessing
| Transformer | Description |
|---|---|
CRMCleaner |
Standardise raw CRM exports — coerce gift_date to datetime64 and gift_amount to float64 |
WealthScreeningImputer |
Leakage-safe wealth imputation (median / mean / zero), fill stats frozen at fit() |
WealthScreeningImputerKNN |
Leakage-safe KNN imputation for wealth-screening vendor columns |
WealthPercentileTransformer |
Per-column wealth percentile rank (0–100); NaN-in → NaN-out |
FiscalYearTransformer |
Fiscal year & quarter from gift dates; configurable start month |
RFMTransformer |
Recency–Frequency–Monetary features for donor segmentation |
ShareOfWalletScorer |
Normalised Share-of-Wallet score + capacity_tier encoding |
MatchingGiftFeaturizer |
Employer matching-gift eligibility and expected-match features |
EncounterTransformer |
Bridge EHR encounters with the CRM; drops identifier-like columns by name |
EncounterRecencyTransformer |
Encounter-date columns → predictive recency features |
GratefulPatientFeaturizer |
Clinical gravity score + service-line capacity weights |
DischargeToSolicitationWindowTransformer |
in_solicitation_window (0/1) and window_position_score [0,1] |
SolicitationWindowTransformer |
Supported alias of DischargeToSolicitationWindowTransformer |
PlannedGivingSignalTransformer |
Bequest / legacy-gift intent vector |
🤖 Models
| Model | Description |
|---|---|
DonorPropensityModel |
Random Forest with predict_affinity_score() on a 0–100 scale |
MajorGiftClassifier |
Calibrated HistGradientBoostingClassifier — NaN-native |
LapsePredictor |
Random Forest for donor lapse, with predict_lapse_score() |
PlannedGivingIntentScorer |
Calibrated bequest-intent scorer, predict_intent_score() |
ShareOfWalletRegressor |
Total giving capacity and untapped-potential ratio |
AskAmountRecommender |
Conservative / target / stretch ask ladder via ask_ladder() |
MovesManagementClassifier |
Multi-class portfolio stage predictor |
FinancialForecastModel |
Hybrid LSTM-ARIMA revenue forecaster, dependency-free |
PropensityScorer |
Constant-probability baseline — a floor to beat, not a scorer |
📊 Metrics, splitters, and the rest
| Symbol | Module | Description |
|---|---|---|
donor_lifetime_value |
metrics |
Discounted LTV annuity |
donor_retention_rate, donor_acquisition_cost |
metrics |
Core campaign KPIs |
cost_per_dollar_raised, fundraising_roi |
metrics |
Campaign efficiency |
gift_concentration_gini, top_donor_share |
metrics |
Portfolio concentration |
disparate_impact_ratio, selection_rate_by_group |
metrics |
Four-fifths-rule fairness audit |
FiscalYearGroupedSplitter |
model_selection |
Walk-forward fiscal-year CV |
donor_feature_importance |
inspection |
Permutation importance for any fitted estimator |
constituent_events_to_features, read_constituent_events |
ingest |
UniSchema bridge |
generate_synthetic_donor_data, load_ciob_fundraising |
datasets |
Synthetic pool and a real CIOB series |
make_donor_dataset, save_model, load_model |
utils |
Labelled fixtures and pipeline persistence |
plot_affinity_distribution, plot_retention_waterfall |
visualisation |
Matplotlib is imported lazily, per function |
UpliftTLearner |
experimental |
T-learner appeal uplift — no API guarantees |
Guides
Tutorials — Building your first model · Avoiding temporal data leakage · Building a grateful-patient pipeline
How-to — Use the CLI · Ingest UniSchema events · Handle missing wealth data · Build grateful-patient features · Recommend ask amounts · Score matching-gift eligibility · Measure campaign efficiency · Audit score fairness · Estimate appeal uplift · Save and load models · Develop and test
Explanation — Design principles · Capacity and loyalty · Fundraising metrics · Compliance considerations · Benchmarks
Roadmap
🔜 Next
philanthropy.visualisation.plot_capacity_heatmap()EnsemblePropensityModel(stacked LapsePredictor + DonorPropensityModel)
Research
S. A. Lalakiya, "AI for Advancement: Predictive Donor Analytics and Fundraising Intelligence at Scale," 2025 IEEE 11th ICCED, IEEE, 2025, doi: 10.1109/ICCED68324.2025.11325064.
This is the library author's own related work on the same problem space, using a
different dataset and its own models. It is not an independent evaluation or a
benchmark of PhilanthroPy. To cite the software itself, see CITATION.cff.
Contributing
See CONTRIBUTING.md for the full local test gate, the
new-test-file workflow, and pre-push hook setup. In short: run make ci before
every push, and never use git push --no-verify.
License
MIT License — see LICENSE for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file philanthropy-0.6.0.tar.gz.
File metadata
- Download URL: philanthropy-0.6.0.tar.gz
- Upload date:
- Size: 120.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3474482115fce3c3775144151d0e04029165c0ebb0213c2a530aa24a4abe3797
|
|
| MD5 |
1fed50acf6243efeb447dab3ccd712c0
|
|
| BLAKE2b-256 |
d63694317ceb90e4755c085403053f63e1055f6ed998a89a6b5d2ff49758aeeb
|
Provenance
The following attestation bundles were made for philanthropy-0.6.0.tar.gz:
Publisher:
publish.yml on PhilanthroPy-Project/PhilanthroPy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
philanthropy-0.6.0.tar.gz -
Subject digest:
3474482115fce3c3775144151d0e04029165c0ebb0213c2a530aa24a4abe3797 - Sigstore transparency entry: 2315159626
- Sigstore integration time:
-
Permalink:
PhilanthroPy-Project/PhilanthroPy@67392aee46dc8e7672be468675a158861ae83b5f -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/PhilanthroPy-Project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@67392aee46dc8e7672be468675a158861ae83b5f -
Trigger Event:
release
-
Statement type:
File details
Details for the file philanthropy-0.6.0-py3-none-any.whl.
File metadata
- Download URL: philanthropy-0.6.0-py3-none-any.whl
- Upload date:
- Size: 134.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09d28d509e1369f7b8dbc8ded8a9b30f5ab0e7245237b4141c4da70a48acac26
|
|
| MD5 |
1f4d32f257aeaf008817a7d8335d366e
|
|
| BLAKE2b-256 |
dd3f61e2825a32485bc9e9a68480fad60e3a00e20f96242fa3328025e4557203
|
Provenance
The following attestation bundles were made for philanthropy-0.6.0-py3-none-any.whl:
Publisher:
publish.yml on PhilanthroPy-Project/PhilanthroPy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
philanthropy-0.6.0-py3-none-any.whl -
Subject digest:
09d28d509e1369f7b8dbc8ded8a9b30f5ab0e7245237b4141c4da70a48acac26 - Sigstore transparency entry: 2315159920
- Sigstore integration time:
-
Permalink:
PhilanthroPy-Project/PhilanthroPy@67392aee46dc8e7672be468675a158861ae83b5f -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/PhilanthroPy-Project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@67392aee46dc8e7672be468675a158861ae83b5f -
Trigger Event:
release
-
Statement type: