Skip to content

Commit

Permalink
BUG: fix patsy raising error with NAs for product-specific demographi…
Browse files Browse the repository at this point in the history
…cs (#132)
  • Loading branch information
jeffgortmaker committed Mar 21, 2023
1 parent 974ae41 commit 758c1cc
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 5 deletions.
9 changes: 5 additions & 4 deletions pyblp/configurations/formulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def __str__(self) -> str:
return ' + '.join(names)

def _build_matrix(
self, data: Mapping, fallback_index: Optional[int] = None) -> (
self, data: Mapping, fallback_index: Optional[int] = None, ignore_na: bool = False) -> (
Tuple[Array, List['ColumnFormulation'], Data]):
"""Convert a mapping from variable names to arrays into the designed matrix, a list of column formulations that
describe the columns of the matrix, and a mapping from variable names to arrays of data underlying the matrix,
Expand Down Expand Up @@ -231,7 +231,7 @@ def _build_matrix(
if symbol.name in underlying_data:
underlying_data[symbol.name] = indicator

matrix = build_matrix(matrix_design, data_mapping)
matrix = build_matrix(matrix_design, data_mapping, ignore_na)
return matrix[:, column_indices], column_formulations, underlying_data

def _build_ids(self, data: Mapping) -> Array:
Expand Down Expand Up @@ -460,7 +460,7 @@ def design_matrix(terms: Sequence[patsy.desc.Term], data: Mapping) -> patsy.desi
return patsy.build.design_matrix_builders([terms], lambda: iter([data]), EvaluationEnvironment([data]))[0]


def build_matrix(design: patsy.design_info.DesignInfo, data: Mapping) -> Array:
def build_matrix(design: patsy.design_info.DesignInfo, data: Mapping, ignore_na: bool = False) -> Array:
"""Build a matrix according to its design and data mapping variable names to arrays."""

# identify the number of rows in the data
Expand All @@ -471,7 +471,8 @@ def build_matrix(design: patsy.design_info.DesignInfo, data: Mapping) -> Array:
return np.ones((size, 1))

# build the matrix and raise an exception if there are any null values
matrix = patsy.build.build_design_matrices([design], data, NA_action='raise')[0].base
na_action = patsy.NAAction(NA_types=[]) if ignore_na else 'raise'
matrix = patsy.build.build_design_matrices([design], data, NA_action=na_action)[0].base

# if the design did not use any data, the matrix may be a single row that needs to be stacked to the proper height
return matrix if matrix.shape[0] == size else np.repeat(matrix[[0]], size, axis=0)
Expand Down
2 changes: 1 addition & 1 deletion pyblp/primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ def build_demographics(
for j in range(max_J):
try:
demographics_j, demographics_formulations, _ = agent_formulation._build_matrix(
data, fallback_index=j
data, fallback_index=j, ignore_na=True
)
except patsy.PatsyError as exception_j:
if j == 0:
Expand Down

0 comments on commit 758c1cc

Please sign in to comment.