diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst old mode 100644 new mode 100755 index 716784f798a54..d733aefa43385 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -205,6 +205,7 @@ Other enhancements (:meth:`~DataFrame.to_parquet` / :func:`read_parquet`) using the `'pyarrow'` engine now preserve those data types with pyarrow >= 1.0.0 (:issue:`20612`). - The ``partition_cols`` argument in :meth:`DataFrame.to_parquet` now accepts a string (:issue:`27117`) +- The ``pandas.np`` submodule is now deprecated. Import numpy directly instead (:issue:`30296`) - :func:`to_parquet` now appropriately handles the ``schema`` argument for user defined schemas in the pyarrow engine. (:issue: `30270`) - DataFrame constructor preserve `ExtensionArray` dtype with `ExtensionArray` (:issue:`11363`) diff --git a/pandas/__init__.py b/pandas/__init__.py index 30b7e5bafe1df..0d4f7bedb77e6 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -105,7 +105,6 @@ to_datetime, to_timedelta, # misc - np, Grouper, factorize, unique, @@ -189,7 +188,6 @@ __git_version__ = v.get("full-revisionid") del get_versions, v - # GH 27101 # TODO: remove Panel compat in 1.0 if pandas.compat.PY37: @@ -211,6 +209,20 @@ class Panel: pass return Panel + + elif name == "np": + + warnings.warn( + "The pandas.np module is deprecated " + "and will be removed from pandas in a future version. " + "Import numpy directly instead", + FutureWarning, + stacklevel=2, + ) + import numpy as np + + return np + elif name in {"SparseSeries", "SparseDataFrame"}: warnings.warn( "The {} class is removed from pandas. Accessing it from " @@ -236,6 +248,28 @@ class SparseDataFrame: class SparseSeries: pass + class __numpy: + def __init__(self): + import numpy as np + import warnings + + self.np = np + self.warnings = warnings + + def __getattr__(self, item): + self.warnings.warn( + "The pandas.np module is deprecated " + "and will be removed from pandas in a future version. " + "Import numpy directly instead", + FutureWarning, + stacklevel=2, + ) + try: + return getattr(self.np, item) + except AttributeError: + raise AttributeError(f"module numpy has no attribute {item}") + + np = __numpy() # module level doc-string __doc__ = """ diff --git a/pandas/core/api.py b/pandas/core/api.py index 5261801600111..b0b65f9d0be34 100644 --- a/pandas/core/api.py +++ b/pandas/core/api.py @@ -1,7 +1,5 @@ # flake8: noqa -import numpy as np - from pandas._libs import NaT, Period, Timedelta, Timestamp from pandas._libs.missing import NA diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index 900ba878e4c0a..d586dbbb72831 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -20,7 +20,6 @@ def check(self, namespace, expected, ignored=None): class TestPDApi(Base): - # these are optionally imported based on testing # & need to be ignored ignored = ["tests", "locale", "conftest"] @@ -93,6 +92,7 @@ class TestPDApi(Base): ] if not compat.PY37: classes.extend(["Panel", "SparseSeries", "SparseDataFrame"]) + deprecated_modules.append("np") # these are already deprecated; awaiting removal deprecated_classes: List[str] = [] @@ -101,7 +101,7 @@ class TestPDApi(Base): deprecated_classes_in_future: List[str] = [] # external modules exposed in pandas namespace - modules = ["np", "datetime"] + modules = ["datetime"] # top-level functions funcs = [ @@ -220,22 +220,43 @@ def test_api(self): self.ignored, ) + def test_depr(self): + deprecated = ( + self.deprecated_modules + + self.deprecated_classes + + self.deprecated_classes_in_future + + self.deprecated_funcs + + self.deprecated_funcs_in_future + ) + for depr in deprecated: + with tm.assert_produces_warning(FutureWarning): + if compat.PY37: + getattr(pd, depr) + else: + deprecated = getattr(pd, depr) + deprecated.__getattr__(dir(deprecated)[-1]) -class TestApi(Base): +def test_np(): + import numpy as np + import warnings + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", FutureWarning) + assert (pd.np.arange(0, 10) == np.arange(0, 10)).all() + + +class TestApi(Base): allowed = ["types", "extensions", "indexers"] def test_api(self): - self.check(api, self.allowed) class TestTesting(Base): - funcs = ["assert_frame_equal", "assert_series_equal", "assert_index_equal"] def test_testing(self): - from pandas import testing self.check(testing, self.funcs) diff --git a/pandas/tests/indexes/period/test_indexing.py b/pandas/tests/indexes/period/test_indexing.py index c8f0d3b3fe553..e17f0af24760c 100644 --- a/pandas/tests/indexes/period/test_indexing.py +++ b/pandas/tests/indexes/period/test_indexing.py @@ -679,7 +679,7 @@ def test_indexing(self): def test_period_index_indexer(self): # GH4125 idx = pd.period_range("2002-01", "2003-12", freq="M") - df = pd.DataFrame(pd.np.random.randn(24, 10), index=idx) + df = pd.DataFrame(np.random.randn(24, 10), index=idx) tm.assert_frame_equal(df, df.loc[idx]) tm.assert_frame_equal(df, df.loc[list(idx)]) tm.assert_frame_equal(df, df.loc[list(idx)])