Skip to content

Open source · scikit-learn native

Predictive donor analytics, done right.

A leakage-safe, pipeline-ready toolkit for nonprofit and academic-medical-center fundraising. Every Tier 1/2 estimator passes scikit-learn's check_estimator.

Leakage-safetrain-only statistics, frozen before transform
check_estimatorevery Tier 1/2 estimator passes scikit-learn's compliance suite
Pipeline-readydrops into sklearn.pipeline.Pipeline
MITopen source, no vendor lock-in

A ranked call list, scored honestly

import pandas as pd
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split

from philanthropy.datasets import generate_synthetic_donor_data
from philanthropy.models import DonorPropensityModel

df = generate_synthetic_donor_data(n_samples=2000, random_state=42)
X = df[["total_gift_amount", "years_active", "event_attendance_count"]].to_numpy()
y = df["is_major_donor"].to_numpy()

# Split BEFORE fitting. Scoring the rows you trained on tells you nothing.
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, stratify=y, random_state=42
)

model = DonorPropensityModel(n_estimators=200, random_state=0)
model.fit(X_train, y_train)

scores = model.predict_affinity_score(X_test)   # 0-100, not a raw probability
auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1])

print(f"held-out ROC-AUC: {auc:.3f}")
print(pd.Series(scores).groupby(y_test).describe()[["count", "mean", "min", "max"]])

0.932held-out ROC-AUC, 500 donors the model never saw

Held-out affinity score by donor class Range and interquartile spread of the 0 to 100 affinity score for 500 held-out donors. Both groups span the full scale at their extremes, but the middle half of non-major donors sits between 1.5 and 38.5 while the middle half of major donors sits between 85.5 and 99.5, 47 points apart. middle halves 47 points apart Major donors: n = 347 · min 18 · Q1 85.5 · median 96.5 · Q3 99.5 · max 100 Major donors n = 347 median 96.5 Non-major donors: n = 153 · min 0 · Q1 1.5 · median 8.5 · Q3 38.5 · max 100 Non-major donors n = 153 median 8.5 0 25 50 75 100 Affinity score
Bar = interquartile range, notch = median, line = full min-to-max range. The tails overlap: a few non-major donors score 100 and a few majors score 18. The middles do not, and that is what a call list needs. Rank by score, work down the list. Fit on the rows you score and the two groups separate perfectly, which is the model reciting its training set, not a result.
Table view: the printed output and the quartiles behind the chart

What the snippet prints:

held-out ROC-AUC: 0.932
   count       mean   min    max
0  153.0  25.019608   0.0  100.0
1  347.0  88.665706  18.0  100.0

The full five-number summary the chart is drawn from:

Group n Min Q1 Median Q3 Max
Non-major donors 153 0.0 1.5 8.5 38.5 100.0
Major donors 347 18.0 85.5 96.5 99.5 100.0

Run it in Colab, zero install

What is PhilanthroPy?

PhilanthroPy is a production-ready 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.

Quick start

Get up and running in seconds:

Current release: 0.7.0

pip install philanthropy gives you 0.7.0. These docs are built from main, which also carries the merged-but-unreleased 1.0.0 work. See Deprecations for the handful of differences that affect you today.

pip install philanthropy
git clone https://github.com/PhilanthroPy-Project/PhilanthroPy.git
cd PhilanthroPy
pip install -e ".[dev]"

Motivation

Predictive fundraising in nonprofits and healthcare foundations is often dominated by proprietary, black-box vendor tools, or brittle, ad-hoc Python scripts that suffer from subtle temporal data leakage across fiscal-year boundaries. Machine-learning code built for the nuances of philanthropic giving was mostly non-existent.

PhilanthroPy exists to change that: a rigorous, open-source, scikit-learn-compatible foundation for donor analytics. It puts advanced fundraising data science within reach of any team, so nonprofits can use their own data to safely and effectively identify their best prospects, without relying entirely on expensive outside vendors.


Key features & capabilities

A comprehensive suite of tools, easy to understand and use:

  • Messy data cleaning


    Standardises raw CRM exports (Salesforce NPSP, Raiser's Edge), fixing dates and currency amounts without crashing. Uses CRMCleaner.

  • Fiscal-calendar awareness


    Nonprofits run on fiscal years (e.g. July–June). PhilanthroPy understands these boundaries natively, preventing future data from leaking into historical models. Uses FiscalYearTransformer.

  • Smart wealth imputation


    Third-party wealth vendors rarely match every record. This estimates missing wealth capacity (like real-estate value) from similar donors using K-nearest neighbours. Uses WealthScreeningImputerKNN.

  • Grateful-patient featurization


    For academic medical centers, translates clinical-encounter histories into major-gift signals while decoupling them from explicit patient identifiers (PHI). This reduces compliance risk but is not formal HIPAA de-identification. See Compliance Considerations. Uses GratefulPatientFeaturizer.

  • Propensity & share of wallet


    Estimators for capacity utilisation (what share of a donor's modelled wealth is estimated philanthropic capacity, not what share of their giving you receive) and the next best engagement step for a gift officer. Uses ShareOfWalletScorer.

Getting started

The quickest way to get familiar with PhilanthroPy is to dive into the Tutorials.

Explore the docs