Skip to main content

Tools to search, analyze, and traverse US nonprofit networks using ProPublica Nonprofit Explorer data.

Project description

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()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nonprofit_networks-0.1.1.tar.gz (899.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nonprofit_networks-0.1.1-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

Details for the file nonprofit_networks-0.1.1.tar.gz.

File metadata

  • Download URL: nonprofit_networks-0.1.1.tar.gz
  • Upload date:
  • Size: 899.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for nonprofit_networks-0.1.1.tar.gz
Algorithm Hash digest
SHA256 84c4c6c2360cb47857706e0c26fa126cab31143a6d06bda0dd96cf7e49d3564a
MD5 399e0047867fa041b8936ea5bf9a3aa0
BLAKE2b-256 186158db1d0ecdde0bac3c530fc9f736a1d3c588265d6b998214dc4ba1dfe101

See more details on using hashes here.

File details

Details for the file nonprofit_networks-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for nonprofit_networks-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 da5f62e63f8e00cb81e5da2de29fa9d4521091bdf327da5d2d3f30bfe0213a96
MD5 b7bc2dd1e04ae04cc63fd8f9a707bd46
BLAKE2b-256 8113fe66c55881061eb959e846f7fb978abe46d2c5cdf08dcec4a22430dd7640

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page