改变Pandas的样式,DataFrame:永久性?

fae0ux8s  于 2022-11-20  发布在  其他
关注(0)|答案(2)|浏览(150)

当我改变一个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 ...部分的输出分配给相同的 Dataframe ,如下所示:

portfolio_df = (portfolio_df ...

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

编辑

检查样式操作返回值的类型
s = (portfolio_df.style.apply(...
我看到的是:

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

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

问题

将样式应用于DataFrame的操作是破坏性操作还是非破坏性操作?答案似乎是样式不会永久更改。现在,如何使样式永久更改?

编辑2

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

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有一个自动呈现 Dataframe 的方法,它考虑了所应用的样式。
否则(在iPython中)它将创建HTML。
将套用样式的传回值指派给变数
s = (portfolio_df.style.apply(...
我可以在Jupyter笔记本中使用它来呈现新的风格。
我的理解是:我不能将 Dataframe 输出到Jupyter笔记本上,并期望它呈现新的样式,但是我可以输出s来显示新的样式。
[1]x1米9英寸
pandas/pandas/io/formats/style.py
文档字符串,第39行。

bksxznpy

bksxznpy1#

我可以给予你两个建议:

1.编写一个简单的函数来显示 Dataframe

这是迄今为止最简单、最不麻烦的解决方案。

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 的代码对panda代码做了最小的修改。这是一个最小的工作示例:

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_
xdnvmnnf

xdnvmnnf2#

尝试使用此函数

df.style.applymap()

相关问题