Pandas 样式`.render()` - 显示前后不同的值

Posted

技术标签:

【中文标题】Pandas 样式`.render()` - 显示前后不同的值【英文标题】:Pandas style `.render()` - Different values before and after display 【发布时间】:2020-08-17 10:44:45 【问题描述】:

我试图在 Jupyter 笔记本中水平显示几个 pandas 数据帧,但遇到了样式器的 html 格式不正确的情况。

我有以下代码sn-p:

import numpy as np
import pandas as pd
from IPython.display import display, HTML

def display_multi_table(table_list, with_display):
    if with_display:
      for t in table_list: display(t)
    return HTML(
        '<table><tr style="background-color:white;">' + 
        ''.join(['<td style="height:300px;width:300px">' + table.render() + '</td>' for table in table_list]) +
        '</tr></table>'
    )

d = dict([(f"column_i", np.random.rand(5)) for i in range(3)])
tables = [pd.DataFrame(d).style.set_caption("Title") for i in range(3)]

以下调用:

display_multi_table(tables, False)

此输出中的结果:

以下调用:

display_multi_table(tables, True)

此输出中的结果:

我的目标:无需调用display即可实现第二个屏幕截图底部的输出。

我尝试过/检查过的事情:

如果我不设置 pandas 数据框的样式,并在数据框上调用 .to_html() 而不是在样式器上调用 .render(),则不存在此问题。但是,我需要它来处理样式数据框。 我确认table.render()在调用display前后返回的值确实不同。

【问题讨论】:

【参考方案1】:

尝试将您的 html 传递到显示中,而不是单独在每个表上调用 display():

import numpy as np
import pandas as pd
from IPython.display import display, HTML

def display_multi_table(table_list, with_display):
    html = HTML(
        '<table><tr style="background-color:white;">' + 
        ''.join(['<td style="height:300px;width:300px">' + table.render() + '</td>' for table in table_list]) +
        '</tr></table>'
    )
    if with_display:
        display(html)
    return html

请注意,如果您在 jupyter 单元格的末尾调用display_multi_table(tables, True),而不将其设置为等于任何值,它将有效地显示表格两次——一次来自display(html),一次来自函数的返回值( return html)。如果这是不希望的行为,则只需将函数调用设置为等于变量 (html = display_multi_table(tables, True)),或将 with_display 设置为 False

【讨论】:

围绕返回、不返回、显示尝试了一系列不同的变化,但没有任何效果。它可能确实与某种包或内核版本有关(正如@Keldorn 在下面指出的那样),但很难确定确切的根本原因。 我看不出问题出在哪里。您上面给出的输出与您编写的代码匹配 display() 就像使用print()。它与函数返回值是分开的,但它会在运行时向您显示您给它的内容。您可以创建一个既能执行print('hello world') 又能执行return 'hello world' 的函数。我的意思是,如果您想要格式化来自 display() 的内容,那么您可以直接将 HTML 传递给 display() 我执行了下面的代码,发现它打印的输出是False。知道为什么会这样吗? ``` h1 = table_list[0].render() for t in table_list: display(t) h2 = table_list[0].render() print(h2 == h1) `` 关于我的最后一条评论,这似乎是因为在我在单个表上调用 display 之前和之后生成的 CSS 不同。我目前的解决方法是在生成 HTML 之前在每个单独的显示之后添加一个 clear_output(wait=True)【参考方案2】:

不是真正的答案,但仍然有一些信息。我无法重现该问题,我已经有了所需的输出。也许是由于某些软件包版本?在此处使用 pandas 1.0.3 和 IPython 7.13.0。

【讨论】:

【参考方案3】:

对于后人,我正在发布我对问题的解决方案:

from IPython.display import display, HTML, clear_output

# source https://github.com/epmoyer/ipy_table/issues/24

def display_multi_table(table_list):
  for t in table_list:
    display(t)
    clear_output(wait=True)

  html = HTML('<table><tr style="background-color:white;">' + ''.join([
      '<td style="black;height:500px;width:600px">' + table.render() + '</td>'
      for table in table_list
  ]) + '</tr></table>')
  return html

我不知道为什么我需要使用clear_output,但它确实有效...

【讨论】:

以上是关于Pandas 样式`.render()` - 显示前后不同的值的主要内容,如果未能解决你的问题,请参考以下文章

以印度逗号样式输出的 Pandas 数据框

pandas之表格样式

pandas之表格样式

用PyQt5来即时显示pandas Dataframe的数据,附qdarkstyle黑夜主题样式(美美哒的黑夜主题)

具有多索引的 Pandas 样式对象

python--pandas样式