Skip to content

Commit

Permalink
MNT: remove legacy product_ids and agent_ids code
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffgortmaker committed May 24, 2022
1 parent 7a00967 commit 3c5d963
Show file tree
Hide file tree
Showing 6 changed files with 13 additions and 78 deletions.
49 changes: 0 additions & 49 deletions pyblp/economies/economy.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,55 +244,6 @@ def _validate_name(self, name: Optional[str], none_valid: bool = True) -> None:
if name not in names:
raise NameError(f"'{name}' is not None or one of the underlying variables, {list(sorted(names))}.")

def _validate_product_ids(self, product_ids: Sequence[Any], market_ids: Optional[Array] = None) -> None:
"""Validate that product IDs either contain None (denoting the outside option) or contain at least one product
ID for each market in the data (or in specific markets if specified). Also verify that each product ID appears
only once in each relevant market.
"""
if self.unique_product_ids.size == 0 and any(i is not None for i in product_ids):
raise ValueError("Product IDs must have been specified.")

if market_ids is None:
market_ids = self.unique_market_ids

for t in market_ids:
counts = []
for product_id in product_ids:
count = 1
if product_id is not None:
count = (self.products.product_ids[self._product_market_indices[t]] == product_id).sum()
if count > 1:
raise ValueError(
f"Product IDs should be unique within markets, but ID '{product_id}' shows up {count} "
f"times in market '{t}'."
)

counts.append(count)

if all(c == 0 for c in counts):
raise ValueError(
f"None of the product_ids {sorted(list(product_ids))} show up in market '{t}' with IDs: "
f"{list(sorted(self.products.product_ids[self._product_market_indices[t]]))}."
)

def _validate_agent_ids(self, agent_ids: Sequence[Any], market_ids: Optional[Array] = None) -> None:
"""Validate that agent IDs have at least one agent ID for each market in the data (or in specific markets if
specified).
"""
if self.unique_agent_ids.size == 0:
raise ValueError("Agent IDs must have been specified.")

if market_ids is None:
market_ids = self.unique_market_ids

for t in market_ids:
counts = [(self.agents.agent_ids[self._agent_market_indices[t]] == i).sum() for i in agent_ids]
if all(c == 0 for c in counts):
raise ValueError(
f"None of the agent_ids {sorted(list(agent_ids))} show up in market '{t}' with IDs: "
f"{list(sorted(self.agents.agent_ids[self._agent_market_indices[t]]))}."
)

def _coerce_optional_firm_ids(self, firm_ids: Optional[Any], market_ids: Optional[Array] = None) -> Array:
"""Coerce optional array-like firm IDs into a column vector and validate it. By default, assume that firm IDs
are for all markets.
Expand Down
6 changes: 3 additions & 3 deletions pyblp/economies/problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,7 @@ class Problem(ProblemEconomy):
It may be convenient to define IDs for different products:
- **product_ids** (`object, optional`) - IDs that identify individual products within markets.
- **product_ids** (`object, optional`) - IDs that identify products within markets.
Finally, clustering groups can be specified to account for within-group correlation while updating the weighting
matrix and estimating standard errors:
Expand Down Expand Up @@ -1268,8 +1268,8 @@ class Problem(ProblemEconomy):
It may be convenient to define IDs for different agents:
- **agent_ids** (`object, optional`) - IDs that identify individual agents within markets. There can be
multiple of the same ID within a market.
- **agent_ids** (`object, optional`) - IDs that identify agents within markets. There can be multiple of the
same ID within a market.
Along with ``market_ids`` and ``agent_ids``, the names of any additional fields can be typically be used as
variables in ``agent_formulation``. The exception is the name ``'demographics'``, which is reserved for use by
Expand Down
6 changes: 3 additions & 3 deletions pyblp/economies/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class Simulation(Economy):
It may be convenient to define IDs for different products:
- **product_ids** (`object, optional`) - IDs that identify individual products within markets.
- **product_ids** (`object, optional`) - IDs that identify products within markets.
To simulate a nested logit or random coefficients nested logit (RCNL) model, nesting groups must be specified:
Expand Down Expand Up @@ -170,8 +170,8 @@ class Simulation(Economy):
It may be convenient to define IDs for different agents:
- **agent_ids** (`object, optional`) - IDs that identify individual agents within markets. There can be
multiple of the same ID within a market.
- **agent_ids** (`object, optional`) - IDs that identify agents within markets. There can be multiple of the
same ID within a market.
Along with ``market_ids`` and ``agent_ids``, the names of any additional fields can typically be used as
variables in ``agent_formulation``. The exception is the name ``'demographics'``, which is reserved for use by
Expand Down
12 changes: 1 addition & 11 deletions pyblp/markets/market.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Market underlying the BLP model."""

import functools
from typing import Any, Dict, List, Optional, Sequence, Tuple
from typing import Any, Dict, List, Optional, Tuple

import numpy as np

Expand Down Expand Up @@ -130,16 +130,6 @@ def __init__(
with np.errstate(all='ignore'):
self.mu = self.compute_mu()

def get_product(self, product_id: Any) -> int:
"""Get the product index associated with a product ID. This assumes that the market has already been validated
to make sure that the product ID appears exactly once.
"""
return int(np.argmax(self.products.product_ids == product_id))

def get_agents_index(self, agent_ids: Sequence[Any]) -> Array:
"""Get an index of agents associated with agent IDs."""
return np.array([i in agent_ids for i in self.agents.agent_ids])

def get_membership_matrix(self) -> Array:
"""Build a membership matrix from nesting IDs."""
if self.membership_matrix is None:
Expand Down
5 changes: 2 additions & 3 deletions pyblp/markets/results_market.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,9 +378,8 @@ def safely_compute_consumer_surplus(

# eliminate any products from the choice set
if eliminate_product_ids is not None:
for product_id in eliminate_product_ids:
if product_id in self.products.product_ids:
j = self.get_product(product_id)
for j, product_id in enumerate(self.products.product_ids):
if product_id in eliminate_product_ids:
exp_utilities[j] = 0

# handle nesting
Expand Down
13 changes: 4 additions & 9 deletions pyblp/primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Products(object):
nesting_ids : `ndarray`
IDs that associate products with nesting groups.
product_ids : `ndarray`
IDs that identify individual products within markets.
IDs that identify products within markets.
clustering_ids : `ndarray`
IDs used to compute clustered standard errors.
ownership : `ndarray`
Expand Down Expand Up @@ -157,13 +157,8 @@ def __new__(
raise ValueError("The firm_ids field of product_data must be one-dimensional.")
if nesting_ids is not None and nesting_ids.shape[1] > 1:
raise ValueError("The nesting_ids field of product_data must be one-dimensional.")
if product_ids is not None:
if product_ids.shape[1] > 1:
raise ValueError("The product_ids field of product_data must be one-dimensional.")
if any(i is None for i in product_ids):
raise ValueError(
"The product_ids field of product_data must not contain None, which denotes the outside option."
)
if product_ids is not None and product_ids.shape[1] > 1:
raise ValueError("The product_ids field of product_data must be one-dimensional.")
if clustering_ids is not None:
if clustering_ids.shape[1] > 1:
raise ValueError("The clustering_ids field of product_data must be one-dimensional.")
Expand Down Expand Up @@ -237,7 +232,7 @@ class Agents(object):
market_ids : `ndarray`
IDs that associate agents with markets.
agent_ids : `ndarray`
IDs that identify individual agents within markets.
IDs that identify agents within markets.
weights : `ndarray`
Integration weights, :math:`w`.
nodes : `ndarray`
Expand Down

0 comments on commit 3c5d963

Please sign in to comment.