diff --git a/tests/pipeline/test_blaze.py b/tests/pipeline/test_blaze.py index 4e717694..35ff75df 100644 --- a/tests/pipeline/test_blaze.py +++ b/tests/pipeline/test_blaze.py @@ -41,6 +41,7 @@ from zipline.testing import ( from zipline.testing.fixtures import WithAssetFinder from zipline.testing.predicates import assert_equal, assert_isidentical from zipline.utils.numpy_utils import float64_dtype, int64_dtype +from zipline.utils.pandas_utils import ignore_pandas_nan_categorical_warning nameof = op.attrgetter('name') diff --git a/tests/pipeline/test_column.py b/tests/pipeline/test_column.py index 717fc53d..99b8b5d7 100644 --- a/tests/pipeline/test_column.py +++ b/tests/pipeline/test_column.py @@ -11,6 +11,7 @@ from zipline.lib.labelarray import LabelArray from zipline.pipeline import Pipeline from zipline.pipeline.data.testing import TestingDataSet as TDS from zipline.testing import chrange, temp_pipeline_engine +from zipline.utils.pandas_utils import ignore_pandas_nan_categorical_warning class LatestTestCase(TestCase): @@ -71,6 +72,8 @@ class LatestTestCase(TestCase): dates_to_test[-1], ) for column in columns: - col_result = result[column.name].unstack() + with ignore_pandas_nan_categorical_warning(): + col_result = result[column.name].unstack() + expected_col_result = self.expected_latest(column, cal_slice) assert_frame_equal(col_result, expected_col_result) diff --git a/zipline/lib/labelarray.py b/zipline/lib/labelarray.py index 0cf1e967..b92faf06 100644 --- a/zipline/lib/labelarray.py +++ b/zipline/lib/labelarray.py @@ -24,6 +24,7 @@ from zipline.utils.numpy_utils import ( int_dtype_with_size_in_bytes, is_object, ) +from zipline.utils.pandas_utils import ignore_pandas_nan_categorical_warning from ._factorize import ( factorize_strings, @@ -284,14 +285,16 @@ class LabelArray(ndarray): """ if len(self.shape) > 1: raise ValueError("Can't convert a 2D array to a categorical.") - return pd.Categorical.from_codes( - self.as_int_array(), - # We need to make a copy because pandas >= 0.17 fails if this - # buffer isn't writeable. - self.categories.copy(), - ordered=False, - name=name, - ) + + with ignore_pandas_nan_categorical_warning(): + return pd.Categorical.from_codes( + self.as_int_array(), + # We need to make a copy because pandas >= 0.17 fails if this + # buffer isn't writeable. + self.categories.copy(), + ordered=False, + name=name, + ) def as_categorical_frame(self, index, columns, name=None): """ diff --git a/zipline/utils/pandas_utils.py b/zipline/utils/pandas_utils.py index a38b437a..121a72ba 100644 --- a/zipline/utils/pandas_utils.py +++ b/zipline/utils/pandas_utils.py @@ -1,8 +1,10 @@ """ Utilities for working with pandas objects. """ +from contextlib import contextmanager from itertools import product import operator as op +import warnings import pandas as pd from distutils.version import StrictVersion @@ -162,6 +164,19 @@ def timedelta_to_integral_minutes(delta): return timedelta_to_integral_seconds(delta) // 60 +@contextmanager +def ignore_pandas_nan_categorical_warning(): + with warnings.catch_warnings(): + # Pandas >= 0.18 doesn't like null-ish values in catgories, but + # avoiding that requires a broader change to how missing values are + # handled in pipeline, so for now just silence the warning. + warnings.filterwarnings( + 'ignore', + category=FutureWarning, + ) + yield + + # Remove when we drop support for 0.17 if pandas_version >= StrictVersion('0.18'): def rolling_mean(arg,