Oregon FQHC Landscape: 2024 Snapshot

Data Engineering
Healthcare
Python
A reproducible HRSA site and organization-level UDS case study
Author

E. Pitzer

Published

September 15, 2026

Introduction

NoteProject Context

This case study is an annual analytical snapshot: it combines an Oregon site-footprint extract from the HRSA Data Warehouse with organization-level 2024 UDS patient measures. These are published administrative sources—not live EHR counts or a continuously current operational census. The site extract and UDS reporting period are dated separately below. To learn how the validated pipeline works, view the Technical Architecture page.

At a Glance

This snapshot contains 330 active registered sites in Oregon, identified by distinct BPHC Assigned Numbers, operated by 33 organizations identified by BHCMIS ID. Site and organization are different analytical grains: distinct registered sites can share a name, building, or coordinates.

Patient-data coverage: 320 of 330 sites (97.0%) link to an organization with a reported patient total. 31 organizations match the configured H80 UDS source; 31 of 33 organizations (93.9%) have reported patient totals. The analytical population contains 31 of 33 represented organizations (93.9%).

Reported organization patient total: 646,289. Each matched organization contributes once. This sum includes patients outside Oregon for multi-state organizations and is not a deduplicated count of Oregon residents or site-level patient volume.

Source periods and provenance: site extract dated 2026-09-14; UDS reporting year 2024, UDS source refresh 2025-05-08. Pipeline build: 2026-09-16T00:16:45.991195+00:00 (UTC), mode: local_snapshot. The dates are shown separately because the site footprint and annual UDS measures are not contemporaneous measurements. A local-snapshot build does not imply a new download.

Quality state: Valid With Warning. 2 Look-Alike organizations are outside the configured H80 UDS source scope. Missing or suppressed patient values remain unavailable rather than being converted to zero.

Organization Payer Mix

This chart includes only the 30 organizations with complete total, Medicaid, and uninsured counts, representing 644,865 reported patients. Organizations with an unavailable or suppressed component are excluded from all slices, rather than treated as zero. This is not an Oregon-resident payer distribution.

Code
# Use a common complete-case denominator for every slice.
payer_orgs = df_orgs.dropna(subset=['total_patients', 'medicaid', 'uninsured'])

total_pop = payer_orgs['total_patients'].sum(min_count=1)
total_medicaid = payer_orgs['medicaid'].sum(min_count=1)
total_uninsured = payer_orgs['uninsured'].sum(min_count=1)
total_other = total_pop - (total_medicaid + total_uninsured)

# Create a mini dataframe for the pie chart
mix_data = pd.DataFrame({
    'Category': ['Medicaid', 'Uninsured', 'Other insurance (including public)'],
    'Patients': [total_medicaid, total_uninsured, total_other]
})

fig_pie = px.pie(
    mix_data,
    values='Patients',
    names='Category',
    color='Category',
    color_discrete_map={
        'Medicaid': '#2c7bb6',    # Blue
        'Uninsured': '#d7191c',   # Red
        'Other insurance (including public)': '#abd9e9' # Light Blue
    },
    hole=0.4,
    height=400,
    title=f"Reported patients (complete payer data): {total_pop:,.0f}*"
)

# Add an annotation explaining the asterisk
fig_pie.add_annotation(
    text="*Includes non-OR patients for multi-state orgs",
    x=0.5, y=-0.15, showarrow=False, font=dict(size=12, color="gray")
)

fig_pie.update_traces(textinfo='percent+label')

# --- THE FIX: ADD BOTTOM MARGIN ---
fig_pie.update_layout(
    margin=dict(t=50, b=80, l=0, r=0) # b=80 gives space for the footnote
)

fig_pie.show()
Figure 1: Payer mix for organizations with complete reported components

Interactive Map

  • Each marker represents a registered site; co-located markers may overlap.
  • Color represents the parent organization’s Medicaid share, not a site-specific rate or geographic density.
  • Gray markers indicate unavailable Medicaid share. Hover for site IDs and addresses; the searchable table includes every site.
Code
fig = px.scatter_map(
    df[df['pct_medicaid'].notna()],
    lat="latitude",
    lon="longitude",
    hover_name="site_name",
    hover_data={
        "latitude": False,
        "longitude": False,
        "total_patients": False,
        "pct_medicaid": False,
        "uninsured": False,
        "medicaid": False,
        "site_id": True,
        "address": True,
        "organization": True,
        "city": True,
        "Patients (fmt)": True,
        "Medicaid %": True
    },
    color="pct_medicaid",
    color_continuous_scale="Viridis",
    zoom=5.5,
    center={"lat": 44.0, "lon": -120.5},
    height=600,
    title="Oregon sites: parent organization Medicaid share"
)

fig.update_traces(marker_size=9)
unavailable = df[df['pct_medicaid'].isna()]
fig.add_trace(go.Scattermap(
    lat=unavailable['latitude'], lon=unavailable['longitude'],
    mode='markers', marker=dict(size=9, color='#777777'),
    name='Medicaid share unavailable',
    text=unavailable['site_name'],
    customdata=unavailable[['site_id', 'address', 'organization']].to_numpy(),
    hovertemplate='%{text}<br>%{customdata[0]}<br>%{customdata[1]}<br>%{customdata[2]}<br>Medicaid share unavailable<extra></extra>'
))
fig.update_layout(
    map_style="open-street-map",
    margin={"r":0,"t":40,"l":0,"b":0},
    coloraxis_colorbar=dict(
        title="% Medicaid",
        thickness=15,
        len=0.5,
        yanchor="bottom", y=0.1,
        xanchor="left", x=0.02,
        bgcolor="rgba(255,255,255,0.8)"
    )
)
fig.show()
Figure 2: Map of Health Center Sites

Analysis: Organization Scale and Medicaid Share

Is there an organization-level relationship between reported patient population and Medicaid share?

The primary predictor is log10 reported patient population. Organizational scale is interpreted proportionally: a change from 5,000 to 10,000 patients is more substantial than a change from 100,000 to 105,000, even though both add 5,000 patients. Logging preserves all eligible organizations, gives each organization equal weight, and reduces geometric domination by the largest organization. Eligibility requires a positive reported patient total and an available Medicaid share; there is no arbitrary minimum-patient filter.

Among 31 distinct organizations, the log-scale Pearson correlation is 0.531 and R² is 0.282. A doubling in reported organization size corresponds to an estimated 5.1 percentage points difference in Medicaid share (95% CI 2.0 to 8.2 percentage points). Spearman’s rank correlation is 0.463, a secondary check on the monotonic pattern.

This is an exploratory association between organizations, not evidence that growth causes Medicaid share to change and not an individual patient-level relationship. Organization size explains only part of the observed variation; substantial payer-mix heterogeneity remains. Large organizations—including Yakima Valley Farm Workers Clinic—remain in the analysis rather than being removed for influence.

Each organization contributes once to the regression and the following Medicaid-share percentiles:

  • 10th percentile: 38.3%
  • Median organization: 55.1%
  • 90th percentile: 74.9%
Code
# df_trend is one row per eligible organization. Every point has equal weight.

fig_corr = px.scatter(
    df_trend,
    x="log10_total_patients",
    y="pct_medicaid",
    hover_name="organization", # Changed to Org Name
    # Update tooltips to be explicit about "Organization" scope
    hover_data={
        "log10_total_patients": False,
        "pct_medicaid": False,
        "Patients (fmt)": True,
        "Medicaid %": True
    },
    trendline="ols",
    labels={"log10_total_patients": "Reported organization patients (log scale)", "pct_medicaid": "Organization Medicaid share"},
    title="Organization size and Medicaid share (equal organization weight)",
    height=500
)

patient_ticks = [1_500, 3_000, 5_000, 10_000, 20_000, 50_000, 100_000, 200_000]
fig_corr.update_layout(
    yaxis_tickformat='.0%',
    xaxis=dict(
        tickmode='array',
        tickvals=[np.log10(value) for value in patient_ticks],
        ticktext=[f"{value / 1000:g}k" for value in patient_ticks]
    )
)
if analysis_publishable:
    fig_corr.show()
else:
    print("Organization-level model withheld: analytical coverage requires human review.")
Figure 3: Organization-level relationship using log10 reported patient population

Search & Explore Data

Explore site locations and parent-organization payer characteristics. These measures do not establish local unmet need. “Unavailable” means the source is unmatched, missing, or suppressed—not zero.

Code
display_cols = ['site_id', 'organization', 'site_name', 'address', 'city', 'total_patients', 'pct_medicaid', 'pct_uninsured']
df_display = df[display_cols].copy()
df_display.columns = ['Site ID', 'Organization', 'Site', 'Address', 'City', 'Org Total Patients', '% Medicaid', '% Uninsured']

# Keep numeric data numeric for sorting; format only the displayed value.
numeric_display = JavascriptFunction("""function(data, type, row, meta) {
    const value = Number(data);
    const missing = data === null || data === "" || !Number.isFinite(value);
    if (type === "sort" || type === "type") return missing ? null : value;
    if (missing) return "Unavailable";
    return meta.col === 5
        ? value.toLocaleString("en-US", {maximumFractionDigits: 0})
        : (value * 100).toFixed(1) + "%";
}""")
show(df_display, classes="display nowrap compact", paging=True, searching=True,
     scrollX=True, columnDefs=[{"targets": [5, 6, 7], "render": numeric_display}])
Table 1
Loading ITables v2.5.2 from the internet... (need help?)

Data Preview

Below are the first five processed site records, sorted by site ID.

Code
# Display a clean table of just a few relevant columns
# USING CORRECTED COLUMN NAME
display_cols = ['site_id', 'site_name', 'address', 'city', 'county', 'type']
df.sort_values('site_id')[display_cols].head(5)
Table 2: Processed site records, ordered by site ID
site_id site_name address city county type
0 BPS-H80-000015 Tigard School Based Health Center 9000 SW Durham Rd BLDG 7110 Tigard Washington Federally Qualified Health Center (FQHC)
1 BPS-H80-000092 BENTON HEALTH CENTER 530 NW 27th St Corvallis Benton Federally Qualified Health Center (FQHC)
2 BPS-H80-000139 Valley Family Health Care - Nyssa Medical Clinic 17 S 3rd St Nyssa Malheur Federally Qualified Health Center (FQHC)
3 BPS-H80-000143 Homeless Outreach, Case Management and Advocacy 323 E 12th Ave Eugene Lane Federally Qualified Health Center (FQHC)
4 BPS-H80-000266 Old Town Clinic 727 W Burnside St Portland Multnomah Federally Qualified Health Center (FQHC)