diff --git a/doc/source/style.ipynb b/doc/source/style.ipynb index a9d9c8de40b702..2cacbb19d81bbf 100644 --- a/doc/source/style.ipynb +++ b/doc/source/style.ipynb @@ -14,7 +14,7 @@ "\n", "You can apply **conditional formatting**, the visual styling of a DataFrame\n", "depending on the data within, by using the ``DataFrame.style`` property.\n", - "This is a property that returns a ``pandas.Styler`` object, which has\n", + "This is a property that returns a ``Styler`` object, which has\n", "useful methods for formatting and displaying DataFrames.\n", "\n", "The styling is accomplished using CSS.\n", @@ -30,8 +30,8 @@ "\n", "Pass your style functions into one of the following methods:\n", "\n", - "- `Styler.applymap`: elementwise\n", - "- `Styler.apply`: column-/row-/table-wise\n", + "- ``Styler.applymap``: elementwise\n", + "- ``Styler.apply``: column-/row-/table-wise\n", "\n", "Both of those methods take a function (and some other keyword arguments) and applies your function to the DataFrame in a certain way.\n", "`Styler.applymap` works through the DataFrame elementwise.\n", @@ -87,7 +87,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style" @@ -105,7 +107,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.highlight_null().render().split('\\n')[:10]" @@ -156,7 +160,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "s = df.style.applymap(color_negative_red)\n", @@ -202,7 +208,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.apply(highlight_max)" @@ -226,7 +234,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.\\\n", @@ -280,7 +290,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.apply(highlight_max, color='darkorange', axis=None)" @@ -328,7 +340,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.apply(highlight_max, subset=['B', 'C', 'D'])" @@ -344,7 +358,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.applymap(color_negative_red,\n", @@ -377,7 +393,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.format(\"{:.2%}\")" @@ -393,7 +411,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.format({'B': \"{:0<4.0f}\", 'D': '{:+.2f}'})" @@ -409,7 +429,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.format({\"B\": lambda x: \"±{:.2f}\".format(abs(x))})" @@ -432,7 +454,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.highlight_null(null_color='red')" @@ -448,7 +472,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "import seaborn as sns\n", @@ -469,7 +495,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# Uses the full color range\n", @@ -479,7 +507,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "# Compress the color range\n", @@ -499,7 +529,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.bar(subset=['A', 'B'], color='#d65f5f')" @@ -515,7 +547,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.highlight_max(axis=0)" @@ -524,7 +558,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.highlight_min(axis=0)" @@ -540,7 +576,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.set_properties(**{'background-color': 'black',\n", @@ -565,7 +603,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df2 = -df\n", @@ -576,7 +616,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "style2 = df2.style\n", @@ -606,7 +648,7 @@ "\n", "Each of these can be specified in two ways:\n", "\n", - "- A keyword argument to `pandas.core.Styler`\n", + "- A keyword argument to `Styler.__init__`\n", "- A call to one of the `.set_` methods, e.g. `.set_caption`\n", "\n", "The best method to use depends on the context. Use the `Styler` constructor when building many styled DataFrames that should all share the same properties. For interactive use, the`.set_` methods are more convenient." @@ -629,7 +671,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "with pd.option_context('display.precision', 2):\n", @@ -649,7 +693,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style\\\n", @@ -682,7 +728,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "df.style.set_caption('Colormaps, with a caption.')\\\n", @@ -708,7 +756,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "from IPython.display import HTML\n", @@ -804,7 +854,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "from IPython.html import widgets\n", @@ -840,7 +892,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "np.random.seed(25)\n", @@ -933,13 +987,15 @@ "source": [ "from jinja2 import Environment, ChoiceLoader, FileSystemLoader\n", "from IPython.display import HTML\n", - "from pandas.io.api import Styler" + "from pandas.io.formats.style import Styler" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "%mkdir templates" @@ -956,7 +1012,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "%%file templates/myhtml.tpl\n", @@ -971,7 +1029,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now that we've created a template, we need to set up a subclass of ``pd.Styler`` that\n", + "Now that we've created a template, we need to set up a subclass of ``Styler`` that\n", "knows about it." ] }, @@ -983,11 +1041,11 @@ }, "outputs": [], "source": [ - "class MyStyler(pd.Styler):\n", + "class MyStyler(Styler):\n", " env = Environment(\n", " loader=ChoiceLoader([\n", " FileSystemLoader(\"templates\"), # contains ours\n", - " pd.Styler.loader, # the default\n", + " Styler.loader, # the default\n", " ])\n", " )\n", " template = env.get_template(\"myhtml.tpl\")" @@ -1007,7 +1065,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "MyStyler(df)" @@ -1023,7 +1083,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "HTML(MyStyler(df).render(table_title=\"Extending Example\"))" @@ -1039,10 +1101,12 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ - "EasyStyler = pd.Styler.from_custom_template(\"templates\", \"myhtml.tpl\")\n", + "EasyStyler = Styler.from_custom_template(\"templates\", \"myhtml.tpl\")\n", "EasyStyler(df)" ] }, @@ -1056,7 +1120,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "with open(\"template_structure.html\") as f:\n", diff --git a/pandas/formats/__init__.py b/pandas/formats/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/pandas/formats/style.py b/pandas/formats/style.py new file mode 100644 index 00000000000000..ec4b4a2cde0c50 --- /dev/null +++ b/pandas/formats/style.py @@ -0,0 +1,7 @@ +import warnings + +warnings.warn("Styler has been moved from pandas.formats.style.Styler" + " to pandas.io.formats.style.Styler. This shim will be" + " removed in pandas 0.21", + FutureWarning) +from pandas.io.formats.style import Styler # noqa diff --git a/pandas/io/api.py b/pandas/io/api.py index 58c388d306721c..e312e7bc2f300f 100644 --- a/pandas/io/api.py +++ b/pandas/io/api.py @@ -17,23 +17,6 @@ from pandas.io.pickle import read_pickle, to_pickle from pandas.io.packers import read_msgpack, to_msgpack from pandas.io.gbq import read_gbq -try: - from pandas.io.formats.style import Styler -except ImportError: - from pandas.compat import add_metaclass as _add_metaclass - from pandas.util.importing import _UnSubclassable - - # We want to *not* raise an ImportError upon importing this module - # We *do* want to raise an ImportError with a custom message - # when the class is instantiated or subclassed. - @_add_metaclass(_UnSubclassable) - class Styler(object): - msg = ("pandas.io.api.Styler requires jinja2. " - "Please install with `conda install jinja2` " - "or `pip install jinja2`") - def __init__(self, *args, **kargs): - raise ImportError(self.msg) - # deprecation, xref #13790 def Term(*args, **kwargs): diff --git a/pandas/tests/api/test_api.py b/pandas/tests/api/test_api.py index 13e6d065382a64..026a36fd9f4f93 100644 --- a/pandas/tests/api/test_api.py +++ b/pandas/tests/api/test_api.py @@ -48,8 +48,7 @@ class TestPDApi(Base, tm.TestCase): 'Period', 'PeriodIndex', 'RangeIndex', 'UInt64Index', 'Series', 'SparseArray', 'SparseDataFrame', 'SparseSeries', 'TimeGrouper', 'Timedelta', - 'TimedeltaIndex', 'Timestamp', 'Interval', 'IntervalIndex', - 'Styler'] + 'TimedeltaIndex', 'Timestamp', 'Interval', 'IntervalIndex'] # these are already deprecated; awaiting removal deprecated_classes = ['WidePanel', 'Panel4D', diff --git a/pandas/tests/io/formats/test_style.py b/pandas/tests/io/formats/test_style.py index c02d94d8918b3e..4fb91c40aba3af 100644 --- a/pandas/tests/io/formats/test_style.py +++ b/pandas/tests/io/formats/test_style.py @@ -747,3 +747,10 @@ def test_from_custom_template(tmpdir): assert result.template is not Styler.template styler = result(pd.DataFrame({"A": [1, 2]})) assert styler.render() + + +def test_shim(): + # https://github.com/pandas-dev/pandas/pull/16059 + # Remove in 0.21 + with pytest.warns(FutureWarning): + from pandas.formats.style import Styler as _styler # noqa diff --git a/pandas/util/importing.py b/pandas/util/importing.py index 9323fb97baac00..e69de29bb2d1d6 100644 --- a/pandas/util/importing.py +++ b/pandas/util/importing.py @@ -1,10 +0,0 @@ -class _UnSubclassable(type): - """ - Metaclass to raise an ImportError when subclassed - """ - msg = "" - - def __init__(cls, name, bases, clsdict): - if len(cls.mro()) > 2: - raise ImportError(cls.msg) - super(_UnSubclassable, cls).__init__(name, bases, clsdict)