Skip to main content

Nonprofit Networks

This codebase is a collection of tools to analyze and understand nonprofit organizations in the United States.

Run on colab Static Badge

This codebase is separated into three components:

Nonprofit Search

With huge thanks to ProPublica for their Nonprofit Explorer API, which provides the data for this project.

from nonprofit_networks import ProPublicaClient

client = ProPublicaClient()
org = client.search("donors trust", state="VA", city="Alexandria").organizations[0]]

Nonprofit Filing Details

filing = client.get_full_filing(org.ein, 2024)

for comp in filing.get_compensations():
    print(
        f"{comp.PersonNm:<30} {comp.TitleTxt:<30} ${comp.ReportableCompFromOrgAmt:>10,.2f} (plus ${comp.OtherCompensationAmt:>10,.2f})"
    )
Kimberly O Dennis              Chair                          $      0.00 (plus $      0.00)
James Piereson                 Vice Chair                     $      0.00 (plus $      0.00)
Thomas E Beach                 Director                       $      0.00 (plus $      0.00)
George GH Coates Jr            Director                       $      0.00 (plus $      0.00)
Lawson R Bader                 President and CEO              $393,490.00 (plus $ 72,461.00)
Jeffrey C Zysik                CFO, COO and Treasurer         $305,587.00 (plus $ 60,430.00)
Peter A Lipsett                Vice President / Secretary     $227,897.00 (plus $ 54,136.00)
Stephen M Johnson              CTO                            $181,250.00 (plus $ 39,742.00)
Gregory P Conko                Vice President of Programs     $225,392.00 (plus $ 46,106.00)
Lukas C Dwelly                 Philanthropic Advisor          $179,667.00 (plus $ 40,346.00)
Stephanie L Giovanetti         Philanthropic Advisor          $156,175.00 (plus $ 23,164.00)
Christopher D Renner           Controller                     $161,704.00 (plus $ 41,228.00)
Elia J Peterson                Assistant Controller           $115,569.00 (plus $ 25,044.00)
filing.get_net_assets()

$1,289,047,383.00

See also,

Method Description
get_compensations Get a list of all reported compensation to staff/board
get_contractor_compensation Get a list of all reported compensation to contractors
get_grant_recipients Get a list of all grant recipients (including EINs)
get_total_revexp Get the total revenue and expenses
get_net_assets Get the net assets
get_rent_income Get a list of rent income
get_disregarded_entities Get a list of disregarded entities
get_related_tax_exempt_orgs Get a list of related tax exempt orgs
get_transactions_related_orgs Get a list of transactions with related orgs

Network Traversal

Grantmakers

This tool makes it easy to traverse the network of grantmaking organizations:

from nonprofit_networks import ProPublicaClient
from nonprofit_networks.network_builder import GrantmakerNetworkBuilder

client = ProPublicaClient()
org = client.search(...).organizations[0]

grant_net = GrantmakerNetworkBuilder(client)
grant_net.build_network(org.ein, depth=2, year=2023)

These networks have vertices of organizations, and the edges have an amount attribute that represents the amount of the grant.

longest_path = nx.dag_longest_path(grant_net.graph)
    print("Longest path:")
    for i in range(len(longest_path) - 1):
        node = longest_path[i]
        next_node = longest_path[i + 1]
        amount = grant_net.graph[node][next_node][0]["grant"].CashGrantAmt
        print(
            # f"{grant_net.graph.nodes[node]['filing'].get_name()} "
            f"${amount:,.2f} -> "
            f"{grant_net.graph.nodes[next_node]['filing'].get_name()}"
        )
Longest Path:

Donor's Trust →
    $12,727,215.00 → BRADLEY IMPACT FUND INC
    $35,000.00 → STATE POLICY NETWORK
    $125,000.00 → Center of the American Experiment
    $109,000.00 → JUDICIAL WATCH INC
    $5,000.00 → COALITIONS FOR AMERICA

(Note that in this example it is clear that the amount does not all come from the same parent organization or from the same grant, since of course later edges can have larger dollar amounts than earlier edges. While this is useful for "tracing the money", it is not useful for understanding the flow of individual grant allocations.)

You can render these graphs with, for example,

import networkx as nx
import matplotlib.pyplot as plt

sanitized_graph = grant_net.graph.copy()
# Remove anything with net_assets == None, and print them
for node in list(sanitized_graph.nodes):
    if sanitized_graph.nodes[node]['filing'].get_net_assets() is None:
        print(f"Removing {sanitized_graph.nodes[node]['filing'].get_name()}")
        sanitized_graph.remove_node(node)

node_sizes = [(sanitized_graph.nodes[node]['filing'].get_net_assets())/100000 for node in sanitized_graph.nodes]
node_colors = [(sanitized_graph.nodes[node]['filing'].get_total_revexp()[0])/100000 for node in sanitized_graph.nodes]

plt.figure(figsize=(16, 16), dpi=100)
pos = nx.spring_layout(sanitized_graph, weight="amount")
nx.draw_networkx_labels(sanitized_graph, pos, labels={node: sanitized_graph.nodes[node]['filing'].get_name() + "\n\n" for node in sanitized_graph.nodes}, font_size=8)
edges = nx.draw_networkx_edges(sanitized_graph, pos, edge_color='gray', alpha=0.5, node_size=node_sizes, width=[sanitized_graph.edges[edge]['amount']**0.1 for edge in sanitized_graph.edges])
nx.draw_networkx_nodes(sanitized_graph, node_size=node_sizes, node_color=node_colors, cmap='viridis', pos=pos)
plt.show()

Metadata

Release files for nonprofit-networks 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nonprofit-networks 0.1.1
File Size Uploaded
nonprofit_networks-0.1.1.tar.gz 899.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nonprofit-networks 0.1.1
File Interpreter ABI Platform
nonprofit_networks-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 924.2 kB

Release files / nonprofit_networks-0.1.1.tar.gz

Download URL nonprofit_networks-0.1.1.tar.gz
Size 899.5 kB
Tags Source
SHA-256 checksum
How to use checksums
84c4c6c2360cb47857706e0c26fa126cab31143a6d06bda0dd96cf7e49d3564a
BLAKE2b-256 checksum
How to use checksums
186158db1d0ecdde0bac3c530fc9f736a1d3c588265d6b998214dc4ba1dfe101
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.9

Release files / nonprofit_networks-0.1.1-py3-none-any.whl

Download URL nonprofit_networks-0.1.1-py3-none-any.whl
Size 24.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
da5f62e63f8e00cb81e5da2de29fa9d4521091bdf327da5d2d3f30bfe0213a96
BLAKE2b-256 checksum
How to use checksums
8113fe66c55881061eb959e846f7fb978abe46d2c5cdf08dcec4a22430dd7640
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.9

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page