改变大熊猫的风格。DataFrame:永久?

Changing style of pandas.DataFrame: Permanently?

提问人:Ugur 提问时间:5/17/2019 最后编辑:Henry EckerUgur 更新时间:3/3/2023 访问量:2423

问:

例如,当我更改样式时,例如pandas.DataFrame

        # color these columns
        color_columns = ['roi', 'percent_of_ath']
        (portfolio_df
            .style
            # color negative numbers red
            .apply(lambda v: 'color: red' if v < 0 else 'color: black',
                   subset=color_columns)
            # color selected cols light blue
            .apply(lambda s: 'background-color: lightblue',
                    subset=color_columns))

应用于 DataFrame 的样式不是永久性的。

为了让它们粘住,我可以将零件的输出分配给相同的数据帧,如下所示:(portfolio_df ...

portfolio_df = (portfolio_df ...

在 Jupyter Notebook 中显示它被覆盖后,我可以看到样式精美的 DataFrame。但是尝试从从模块导入的函数中更改样式,我失败了。我在函数中构造 DataFrame,更改样式,从函数返回(现在)样式化的 DataFrame,将其显示在 Jupyter Notebook 中,我看到一个非样式化的 DataFrame。portfolio_df

编辑

检查样式设置操作的返回值的类型

s = (portfolio_df.style.apply(...

我看到这个:

>>> type(s)
pandas.io.formats.style.Styler

因此,该操作不返回 DataFrame,而是返回对象。我错误地认为我可以将这个返回值重新分配给我的原始 DataFrame,从而覆盖它并使样式更改永久化。...Styler

问题

将样式应用于 DataFrame 的操作是破坏性操作还是非破坏性操作?答案似乎是风格不会永久改变。现在,我怎样才能让它永久改变?

编辑 2

查看 的源代码,我查看了文档字符串(参见 [1]):Pandasclass Styler

    If using in the Jupyter notebook, Styler has defined a ``_repr_html_``
    to automatically render itself. Otherwise call Styler.render to get
    the generated HTML.

因此,在 Jupyter 笔记本中,Styler 具有一个自动呈现数据帧的方法,并遵循应用的样式。

否则(在 iPython 中)它会创建 HTML。

将应用样式的返回值分配给变量

s = (portfolio_df.style.apply(...

我可以在 Jupyter 笔记本中使用它来呈现新样式。

我的理解是:我无法将我的数据帧输出到 Jupyter 笔记本中并期望它呈现新样式。但我可以输出以显示新风格。s


[1] 在class Styler

pandas/pandas/io/formats/style.py

Docstring,第 39 行。

python pandas jupyter-notebook pandas-样式

评论

0赞 G. Anderson 5/17/2019
请编辑您的帖子以包含错误的完整追溯
0赞 layser 6/11/2020
我有一个类似的用例,我想应用一种样式并转换为乳胶。
0赞 Ynjxsjmh 6/3/2022
你能详细说明一下吗 但是尝试从从模块导入的函数中更改样式,我失败了。 用你的代码?

答:

-4赞 Mathanraj-Sharma 5/17/2019 #1

尝试使用此功能

df.style.applymap()
0赞 MYK 11/17/2022 #2

我可以给你两个建议:

1. 编写一个简单的函数来显示您的数据帧

这是迄今为止最简单、最不容易解决的解决方案。你可以这样写:

def my_style(df:pd.DataFrame, color_columns:list[str]=['roi', 'percent_of_ath']):
    return (df
            .style
            .applymap(lambda v: 'color: red' if v < 0 
                                 else None, subset=color_columns)
           )    

这样,您就可以编写如下代码:

df.pipe(my_style) # This will output a formatted dataframe

from IPython.display import display 

# This will print a nicely formatted dataframe
def my_display(df:pd.DataFrame, style=my_style):
    display(df.pipe(style))

2. 覆盖 Pandas _repr_html_方法

我不建议这样做,但这就是你要求的;)

from pandas._config import get_option
from pandas.io.formats import format as fmt

def _my_repr_html_(self) -> str | None:
        """
        Return a html representation for a particular DataFrame.

        Mainly for IPython notebook.
        """
        if self._info_repr():
            buf = StringIO()
            self.info(buf=buf)
            # need to escape the <class>, should be the first line.
            val = buf.getvalue().replace("<", r"&lt;", 1)
            val = val.replace(">", r"&gt;", 1)
            return "<pre>" + val + "</pre>"

        if get_option("display.notebook_repr_html"):
            max_rows = get_option("display.max_rows")
            min_rows = get_option("display.min_rows")
            max_cols = get_option("display.max_columns")
            show_dimensions = get_option("display.show_dimensions")

            formatter = fmt.DataFrameFormatter(
                self,
                columns=None,
                col_space=None,
                na_rep="NaN",
                formatters=None,
                float_format=None,
                sparsify=None,
                justify=None,
                index_names=True,
                header=True,
                index=True,
                bold_rows=True,
                escape=True,
                max_rows=max_rows,
                min_rows=min_rows,
                max_cols=max_cols,
                show_dimensions=show_dimensions,
                decimal=".",
            )
            # return fmt.DataFrameRenderer(formatter).to_html(notebook=True)
            return self.pipe(my_style).to_html(notebook=True) # <<<< !!! HERE !!! 
        else:
            return None
        
df.pipe(_my_repr_html_)

pd.DataFrame._repr_html_ = _my_repr_html_

小心!此示例代码不处理很长或很宽的 DataFrame。

编辑:

上面用于覆盖repr_html的代码对 pandas 代码进行了最少的编辑。这是一个最小的工作示例:

def my_style(df:pd.DataFrame, color_columns:list[str]=['roi', 'percent_of_ath']):
    return (df.style.applymap(
            lambda v: 'color: red' if v < 0 else None, subset=color_columns)
           ) 

def _my_repr_html_(self) -> str | None:
    return self.pipe(my_style)._repr_html_() # <<<< !!! HERE !!! 
        
pd.DataFrame._repr_html_ = _my_repr_html_
0赞 dustindorroh 3/3/2023 #3

我在我的 ipython 配置文件中放置了 pandas 选项的启动脚本。

例如,这是我的 ipython 启动的样子

$ ls ~/.ipython/profile_default/startup/
10-pandas.py  11-import-modules.py  README

我的熊猫设置如下所示

def setup_pandas_options(max_rows=50):
    import pandas as pd
    pd.set_option('display.expand_frame_repr', True)
    pd.set_option('display.max_rows', max_rows)
    pd.set_option('display.max_columns', 100)
    pd.set_option('display.max_colwidth',180)
    pd.set_option('display.width', 200)

然后我的 inports 启动看起来像:

try:
    import os
    import sys
    import numpy as np
    import pandas as pd
    setup_pandas_options()
except ModuleNotFoundError:
    pass

您可能需要在最初设置配置文件。