Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 13 additions & 26 deletions src/__tests__/pages/policy/PolicyRightSidebar.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fireEvent, render, waitFor } from "@testing-library/react";
import { render, waitFor } from "@testing-library/react";
import { BrowserRouter, useSearchParams } from "react-router-dom";
import PolicyRightSidebar, {
SinglePolicyChange,
Expand Down Expand Up @@ -48,7 +48,7 @@ const standardPolicyUK = {
};

describe("Enhanced CPS selector", () => {
test("Should be present for the US site", async () => {
test("Should not be present (selector removed)", async () => {
const testSearchParams = {
focus: "gov",
};
Expand All @@ -67,10 +67,10 @@ describe("Enhanced CPS selector", () => {
defaultOpen: true,
};

const { getByTestId } = render(<PolicyRightSidebar {...props} />);
const { queryByTestId } = render(<PolicyRightSidebar {...props} />);

await waitFor(() => {
expect(getByTestId("enhanced_cps_switch")).toBeInTheDocument();
expect(queryByTestId("enhanced_cps_switch")).not.toBeInTheDocument();
});
});
test("Should not render for the UK site", async () => {
Expand Down Expand Up @@ -98,7 +98,7 @@ describe("Enhanced CPS selector", () => {
expect(queryByTestId("enhanced_cps_switch")).not.toBeInTheDocument();
});
});
test("Should be enabled when region is 'us'", async () => {
test("Should not be present when region is 'us' (selector removed)", async () => {
const testSearchParams = {
focus: "gov",
region: "us",
Expand All @@ -118,13 +118,11 @@ describe("Enhanced CPS selector", () => {
defaultOpen: true,
};

const { getByTestId } = render(<PolicyRightSidebar {...props} />);
const { queryByTestId } = render(<PolicyRightSidebar {...props} />);

expect(getByTestId("enhanced_cps_switch").classList).not.toContain(
"ant-switch-disabled",
);
expect(queryByTestId("enhanced_cps_switch")).not.toBeInTheDocument();
});
test("Should be enabled when region is 'null'", async () => {
test("Should not be present when region is 'null' (selector removed)", async () => {
const testSearchParams = {
focus: "gov",
};
Expand All @@ -143,24 +141,16 @@ describe("Enhanced CPS selector", () => {
defaultOpen: true,
};

const { getByTestId } = render(<PolicyRightSidebar {...props} />);
const { queryByTestId } = render(<PolicyRightSidebar {...props} />);

expect(getByTestId("enhanced_cps_switch").classList).not.toContain(
"ant-switch-disabled",
);
expect(queryByTestId("enhanced_cps_switch")).not.toBeInTheDocument();
});
test("Should change region when selected", () => {
test("Should not have selector to change dataset (selector removed)", () => {
const testSearchParams = {
focus: "gov",
region: "us",
};

const expectedSearchParams = {
focus: "gov",
region: "us",
dataset: "enhanced_cps",
};

const mockSetSearchParams = jest.fn();

useSearchParams.mockImplementation(() => {
Expand All @@ -177,11 +167,8 @@ describe("Enhanced CPS selector", () => {
defaultOpen: true,
};

const { getByTestId } = render(<PolicyRightSidebar {...props} />);
fireEvent.click(getByTestId("enhanced_cps_switch"));
expect(mockSetSearchParams).toHaveBeenCalledWith(
new URLSearchParams(expectedSearchParams),
);
const { queryByTestId } = render(<PolicyRightSidebar {...props} />);
expect(queryByTestId("enhanced_cps_switch")).not.toBeInTheDocument();
});
});

Expand Down
Binary file added src/images/posts/enhanced-cps-launch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
102 changes: 0 additions & 102 deletions src/pages/policy/PolicyRightSidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -456,100 +456,6 @@ function FullLiteToggle() {
* @param {Number|String} timePeriod The year the simulation should run over
* @returns {import("react").ReactElement}
*/
function DatasetSelector(props) {
const { presentDataset, timePeriod } = props;
const [isChecked, setIsChecked] = useState(confirmIsChecked(presentDataset));
const [searchParams, setSearchParams] = useSearchParams();
const displayCategory = useDisplayCategory();

function confirmIsChecked(presentDataset) {
// Define presentDataset value that activates check
const checkValue = "enhanced_cps";
if (presentDataset === checkValue) {
return true;
}
return false;
}

// Determine whether slider should be enabled or disabled
function shouldEnableSlider(timePeriod) {
// Define earliest year slider should be shown for
const sliderStartYear = 2024;

// Return whether or not slider should be enabled
// Null timePeriod reflects no URL param setting yet -
// this is actually default behavior
if (!timePeriod || timePeriod >= sliderStartYear) {
return true;
}

return false;
}

function handleChange() {
// First, safety check - if the button isn't even
// supposed to be shown, do nothing
if (!shouldEnableSlider(timePeriod)) {
return;
}

// Duplicate the existing search params
let newSearch = copySearchParams(searchParams);

// Set params accordingly
if (isChecked) {
newSearch.delete("dataset");
setIsChecked(false);
} else {
newSearch.set("dataset", "enhanced_cps");
setIsChecked(true);
}
setSearchParams(newSearch);
}

return (
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
gap: "10px",
}}
>
<Switch
data-testid="enhanced_cps_switch"
size={displayCategory !== "mobile" && "small"}
onChange={handleChange}
disabled={!shouldEnableSlider(timePeriod)}
checked={presentDataset === "enhanced_cps" ? true : false}
/>
<p
style={{
margin: 0,
fontSize: displayCategory !== "mobile" && "0.95em",
color: !shouldEnableSlider(timePeriod) && "rgba(0,0,0,0.5)",
cursor: !shouldEnableSlider(timePeriod) && "not-allowed",
}}
>
Use Enhanced CPS (beta)
</p>
<Tooltip
placement="topRight"
title="Currently available for US-wide simulations only."
trigger={displayCategory === "mobile" ? "click" : "hover"}
>
<QuestionCircleOutlined
style={{
color: "rgba(0, 0, 0, 0.85)",
opacity: 0.85,
cursor: "pointer",
}}
/>
</Tooltip>
</div>
);
}

function PolicyNamer(props) {
const { policy, metadata } = props;
Expand Down Expand Up @@ -838,8 +744,6 @@ export default function PolicyRightSidebar(props) {

const isMultiYear = determineIfMultiYear(searchParams);

let dataset = searchParams.get("dataset");

const options = metadata.economy_options.region.map((stateAbbreviation) => {
return { value: stateAbbreviation.name, label: stateAbbreviation.label };
});
Expand Down Expand Up @@ -1138,12 +1042,6 @@ export default function PolicyRightSidebar(props) {
}}
/>
</div>
{metadata.countryId === "us" && (
<DatasetSelector
presentDataset={dataset}
timePeriod={timePeriod}
/>
)}
{MULTI_YEAR_SELECTOR_PERMITTED_COUNTRIES.includes(
metadata.countryId,
) && (
Expand Down
99 changes: 99 additions & 0 deletions src/posts/articles/enhanced-cps-launch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
We're excited to announce the full launch of the Enhanced Current Population Survey (Enhanced CPS). This comprehensive dataset powers PolicyEngine's microsimulation modeling with unprecedented accuracy, enabling precise analysis of tax and benefit reforms across the United States.

Building on extensive development and testing since our [beta launch](/us/research/enhanced-cps-beta), the Enhanced CPS now includes sophisticated imputation models for income sources and household characteristics that were previously unavailable or underreported in survey data. These improvements provide a more complete picture of American households' economic circumstances. Learn more about our [methodology](https://policyengine.github.io/policyengine-us-data/methodology) and [data sources](https://policyengine.github.io/policyengine-us-data/data).

## New features

### Income source imputations

The Enhanced CPS now includes machine learning-based imputations for income sources that are frequently underreported in surveys:

**Tip income**: Using employer-reported data from the Survey of Income and Program Participation (SIPP), we impute tip income based on employment income, age, and household composition. This enhancement enables accurate analysis of proposals to exempt tips from taxation. See our [imputation methodology documentation](https://policyengine.github.io/policyengine-us-data/methodology#imputation) for technical details.

**Overtime premiums**: We calculate overtime income using hours worked, occupation codes, and Fair Labor Standards Act exemption status, allowing accurate modeling of overtime exemption proposals.

**Auto loan interest**: Imputed from the Survey of Consumer Finances (SCF), this addition enables analysis of proposals to make auto loan interest deductible.

### Immigration status imputation

We've implemented the ASEC Undocumented Algorithm to impute Social Security Number card types, enabling more accurate modeling of policies with citizenship or work authorization requirements. This process-of-elimination approach examines 14 conditions to identify likely undocumented individuals, calibrated to match external population estimates. Details are available in our [demographic imputation section](https://policyengine.github.io/policyengine-us-data/methodology#demographic-imputation).

### Technical infrastructure improvements

**Two-stage methodology**: Our approach combines sophisticated imputation with advanced reweighting techniques. First, we use Quantile Regression Forests (QRF) to impute missing variables from multiple data sources, preserving realistic variation and capturing conditional distribution tails. Second, we apply gradient-based optimization with PyTorch to reweight households, matching administrative targets while maintaining the survey's statistical properties.

![Enhanced CPS methodology flowchart showing the two-stage process of imputation and reweighting](/images/posts/enhanced-cps-launch-flowchart.png)

Copilot AI Aug 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The referenced image /images/posts/enhanced-cps-launch-flowchart.png is not included in this PR. Ensure the image file exists in the correct location before publishing the blog post.

Copilot uses AI. Check for mistakes.

The process flow integrates five source datasets (CPS ASEC, IRS PUF, SIPP, SCF, ACS) that are aged to the target year. Through QRF imputation, we create two enhanced CPS variants: one with missing PUF variables filled in, and another with existing variables replaced by PUF values. These datasets then undergo reweighting optimization to produce the final Enhanced CPS dataset. [View our detailed methodology documentation](https://policyengine.github.io/policyengine-us-data/methodology).

**Microimpute package**: We've developed and adopted [`microimpute`](https://github.com/PolicyEngine/microimpute), a new open-source Python package that automates our QRF-based imputation methods. This package makes our imputation methodology more transparent and reusable.

**Advanced reweighting with L0 regularization**: Our reweighting process uses log-transformed weights with dropout regularization and incorporates an L0 penalty for sparsity. This ensures positive weights while preventing overfitting and maintaining interpretability. The optimization minimizes mean squared relative error using the Adam optimizer.

**Enhanced validation**: Our [calibration process](https://policyengine.github.io/policyengine-us-data/methodology#calibration) targets 9,168 administrative totals from sources including IRS SOI, Census, CBO/Treasury, and JCT data, ensuring the Enhanced CPS accurately represents:

- Income components by source
- Benefit program enrollment
- Demographic distributions
- Geographic population counts

## Upcoming developments

### State and local calibration

With support from [Arnold Ventures](https://www.arnoldventures.org/), we're extending the Enhanced CPS to provide accurate estimates for every state and congressional district. This follows our successful implementation of local-area microsimulation in the UK, funded by the [Nuffield Foundation](https://www.nuffieldfoundation.org/).

Once complete, the Enhanced CPS will become the default for state-level analysis as well, and PolicyEngine users will be able to analyze the impacts of federal and state policy reforms on:

- Poverty rates by state and congressional district
- Income inequality measures for local areas
- Winners and losers from reforms in specific districts
- Distributional impacts by income decile for each state

### Microcalibrate package

We're developing [`microcalibrate`](https://github.com/PolicyEngine/microcalibrate), a next-generation reweighting package that enhances our current gradient descent approach. This package will offer:

- Faster convergence to calibration targets
- Better preservation of the original survey's covariance structure
- More flexible loss functions for different use cases
- Easier extension to multi-area calibration

### Additional data enhancements

We currently integrate data from the Survey of Consumer Finances (for auto loan interest) and American Community Survey (for housing costs). Future enhancements will expand these integrations:

- **Wealth modeling from SCF**: Comprehensive asset and debt data for modeling asset limits in SNAP, SSI, and other means-tested programs, similar to our [wealth modeling in the UK](https://policyengine.org/uk/research/uk-the-new-policyengine)
- **Consumer Expenditure Survey**: Consumption patterns for modeling sales taxes, carbon pricing, and other consumption-based policies
- **Expanded ACS integration**: Additional geographic and demographic detail for state and local policy analysis

## Using the Enhanced CPS

The Enhanced CPS is now the exclusive dataset for nationwide PolicyEngine US analyses. We've removed the dataset selector to streamline the user experience鈥攖he Enhanced CPS automatically powers all federal policy simulations, while state-specific analyses continue to use the standard CPS until our local calibration is complete.

You can access the Enhanced CPS through:

**Web interface**: The Enhanced CPS powers all nationwide calculations at [policyengine.org/us](https://policyengine.org/us)

**Python package**: Works by default for our `Microsimulation` calls.

**Direct download**: For Python users, the data automatically downloads from our Hugging Face repository when you instantiate a simulation. The files are stored at [`hf://policyengine/policyengine-us-data`](https://huggingface.co/policyengine/policyengine-us-data)

## Technical details

For researchers interested in our methodology:

- **Full technical documentation**: [PolicyEngine US Data documentation](https://policyengine.github.io/policyengine-us-data)
- **Data integration methodology**: [Imputation and fusion techniques](https://policyengine.github.io/policyengine-us-data/methodology#data-fusion)
- **Calibration approach**: [Reweighting methodology](https://policyengine.github.io/policyengine-us-data/methodology#reweighting)
- **Validation results**: [Comparison with administrative data](https://policyengine.github.io/policyengine-us-data/discussion)
- **Implementation code**: [Microimpute package](https://github.com/PolicyEngine/microimpute)
- **Source code**: [Enhanced CPS on GitHub](https://github.com/PolicyEngine/policyengine-us-data/tree/main/policyengine_us_data/datasets/cps)

## Conclusion

The Enhanced CPS represents a major advancement in open-source microsimulation data. By [combining the demographic richness of the Current Population Survey with tax detail from IRS records](https://policyengine.github.io/policyengine-us-data/background) and sophisticated imputation techniques, we've created a dataset that supports comprehensive analysis of both tax and benefit policies.

As we expand to state and local calibration, the Enhanced CPS will enable unprecedented granularity in policy analysis鈥攅mpowering lawmakers, researchers, and citizens to understand how proposed reforms would affect their communities.

We welcome feedback and collaboration as we continue improving this foundational infrastructure for evidence-based policymaking. For questions or to contribute to development, please visit our [GitHub repositories](https://github.com/PolicyEngine) or [contact us](mailto:hello@policyengine.org).
9 changes: 9 additions & 0 deletions src/posts/posts.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
[
{
"title": "Enhanced CPS full launch: Comprehensive microdata for policy analysis",
"description": "The Enhanced Current Population Survey now includes tip, overtime, and auto loan interest imputations, plus upcoming state and congressional district calibration.",
"date": "2025-08-08",
"tags": ["us", "data", "featured"],
"filename": "enhanced-cps-launch.md",
"image": "enhanced-cps-launch.png",

Copilot AI Aug 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The referenced image enhanced-cps-launch.png is not included in this PR. Verify the image file exists in the expected location for the blog post metadata.

Copilot uses AI. Check for mistakes.
"authors": ["max-ghenis", "nikhil-woodruff"]
},
{
"title": "Analysis of individual income tax provisions in the final reconciliation bill",
"description": "Our simulation projects a reduction in federal revenues of $3.8 trillion from 2026 to 2035 compared to current law.",
Expand Down
Loading