econirl.NFXP
- class econirl.NFXP(n_states=90, n_actions=2, discount=0.9999, utility='linear_cost', se_method='robust', verbose=False)[source]
Bases:
objectSklearn-style NFXP estimator for dynamic discrete choice models.
The Nested Fixed Point (NFXP) algorithm estimates utility parameters by nesting the solution of the Bellman equation within likelihood maximization. This is the classic approach from Rust (1987, 1988).
- Parameters:
n_states (int, default=90) – Number of discrete states (e.g., mileage bins).
n_actions (int, default=2) – Number of discrete actions (e.g., keep/replace).
discount (float, default=0.9999) – Time discount factor (beta).
utility (str or RewardSpec, default="linear_cost") – Utility specification. Pass
"linear_cost"for the classic Rust bus model (u = -theta_c * s * (1-a) - RC * a), or aRewardSpecfor custom features.se_method (str, default="robust") – Method for computing standard errors. Options: “robust”, “asymptotic”.
verbose (bool, default=False) – Whether to print progress messages during estimation.
- Variables:
params (dict) – Estimated parameters after fitting. Keys are parameter names (e.g., “theta_c”, “RC”) and values are point estimates.
se (dict) – Standard errors for each parameter.
coef (numpy.ndarray) – Coefficients as a numpy array (sklearn convention).
log_likelihood (float) – Maximized log-likelihood value.
pvalues (dict) – P-values for each parameter (from Wald t-test).
policy (numpy.ndarray) – Estimated choice probabilities P(a|s) of shape (n_states, n_actions).
value (numpy.ndarray) – Estimated value function V(s) of shape (n_states,).
value_function (numpy.ndarray) – Alias for
value_(backward compatibility).transitions (numpy.ndarray) – Transition probability matrix (n_states x n_states).
converged (bool) – Whether the optimization converged.
reward_spec (RewardSpec) – The reward specification used for estimation.
Examples
>>> from econirl.estimators import NFXP >>> import pandas as pd >>> >>> df = pd.DataFrame({ ... "bus_id": [0, 0, 1, 1], ... "mileage": [10, 20, 15, 30], ... "replaced": [0, 0, 0, 1], ... }) >>> >>> model = NFXP(n_states=90) >>> model.fit(df, state="mileage", action="replaced", id="bus_id") >>> print(model.params_)
- __init__(n_states=90, n_actions=2, discount=0.9999, utility='linear_cost', se_method='robust', verbose=False)[source]
Initialize the NFXP estimator.
- Parameters:
n_states (int, default=90) – Number of discrete states.
n_actions (int, default=2) – Number of discrete actions.
discount (float, default=0.9999) – Time discount factor (beta).
utility (str or RewardSpec, default="linear_cost") – Utility specification to use. Pass
"linear_cost"for the classic Rust bus model, or aRewardSpecfor custom features.se_method (str, default="robust") – Method for computing standard errors.
verbose (bool, default=False) – Whether to print progress messages.
- fit(data, state=None, action=None, id=None, transitions=None, reward=None)[source]
Fit the NFXP estimator to data.
- Parameters:
data (pandas.DataFrame or Panel or TrajectoryPanel) – Panel data with observations. When a DataFrame is passed,
state,action, andidcolumn names are required. When a Panel/TrajectoryPanel is passed, column names are ignored.state (str, optional) – Column name for the state variable (required for DataFrame input).
action (str, optional) – Column name for the action variable (required for DataFrame input).
id (str, optional) – Column name for the individual identifier (required for DataFrame input).
transitions (numpy.ndarray, optional) – Pre-estimated transition matrix of shape (n_states, n_states). If None, transitions are estimated from the data.
reward (RewardSpec, optional) – Reward/utility specification. If provided, overrides the
utilityparameter passed at construction time.
- Returns:
self – Returns self for method chaining.
- Return type:
- property reward_matrix_: ndarray | None
Structural reward matrix R(s,a) of shape (n_states, n_actions).
Computes the utility matrix from the fitted parameters and the feature specification. Returns None if the model has not been fitted.
- summary()[source]
Generate a formatted summary of estimation results.
- Returns:
Human-readable summary of the estimation.
- Return type:
- conf_int(alpha=0.05)[source]
Compute confidence intervals for parameters.
- Parameters:
alpha (float, default=0.05) – Significance level. Returns (1 - alpha) confidence intervals.
- Returns:
{param_name: (lower, upper)}confidence intervals.- Return type:
- Raises:
RuntimeError – If the model has not been fitted yet.
- predict_proba(states)[source]
Predict choice probabilities for given states.
- Parameters:
states (numpy.ndarray) – Array of state indices.
- Returns:
Choice probabilities of shape (len(states), n_actions). Each row sums to 1.
- Return type:
- simulate(n_agents, n_periods, seed=None)[source]
Simulate choices under the estimated policy.
Generates synthetic data by simulating agents making decisions according to the fitted model. Each agent starts at state 0 and evolves according to the estimated transition probabilities and choice probabilities.
- Parameters:
- Returns:
DataFrame with columns: - agent_id: Identifier for each agent (0 to n_agents-1) - period: Time period (0 to n_periods-1) - state: State at the beginning of the period - action: Action taken (sampled from estimated policy)
- Return type:
- Raises:
RuntimeError – If the model has not been fitted yet.
Examples
>>> model = NFXP(n_states=90) >>> model.fit(data, state="mileage", action="replaced", id="bus_id") >>> sim_data = model.simulate(n_agents=100, n_periods=50, seed=42) >>> print(sim_data.head())
- counterfactual(**param_changes)[source]
Compute outcomes under different parameter values.
Performs counterfactual analysis by solving the dynamic programming problem under alternative parameter values. This enables “what if” questions like “what would the policy be if RC was 15 instead of 10?”
- Parameters:
**param_changes (float) – Keyword arguments specifying parameter changes. Keys must be valid parameter names (e.g., “theta_c”, “RC”). Values are the counterfactual parameter values.
- Returns:
Object containing: - params: Dictionary of all parameter values used - value_function: V(s) under new parameters - policy: P(a|s) under new parameters
- Return type:
CounterfactualResult
- Raises:
RuntimeError – If the model has not been fitted yet.
ValueError – If an unknown parameter name is provided.
Examples
>>> model = NFXP(n_states=90) >>> model.fit(data, state="mileage", action="replaced", id="bus_id") >>> >>> # What if replacement cost was higher? >>> cf = model.counterfactual(RC=15.0) >>> print(f"Original RC: {model.params_['RC']:.2f}") >>> print(f"Counterfactual RC: {cf.params['RC']:.2f}") >>> print(f"P(replace|state=50) changes from " ... f"{model.predict_proba(np.array([50]))[0,1]:.3f} to " ... f"{cf.policy[50,1]:.3f}") >>> >>> # Multiple parameter changes >>> cf2 = model.counterfactual(RC=15.0, theta_c=0.05)