Jupyter笔记本并排显示两只熊猫桌

Sal*_*ali 73 pandas ipython-notebook jupyter-notebook

我有两个pandas数据帧,我想在Jupyter笔记本中显示它们.

做类似的事情:

display(df1)
display(df2)
Run Code Online (Sandbox Code Playgroud)

在另一个下面显示它们:

在此输入图像描述

我想在第一个数据框右侧有第二个数据帧.有一个类似的问题,但看起来有人对在显示它们之间的差异的一个数据框中合并它们感到满意.

这对我不起作用.在我的例子中,数据帧可以表示完全不同的(不可比较的元素),并且它们的大小可以不同.因此,我的主要目标是节省空间.

ntg*_*ntg 82

我最终编写了一个可以执行此操作的函数:

from IPython.display import display_html
def display_side_by_side(*args):
    html_str=''
    for df in args:
        html_str+=df.to_html()
    display_html(html_str.replace('table','table style="display:inline"'),raw=True)
Run Code Online (Sandbox Code Playgroud)

用法示例:

df1 = pd.DataFrame(np.arange(12).reshape((3,4)),columns=['A','B','C','D',])
df2 = pd.DataFrame(np.arange(16).reshape((4,4)),columns=['A','B','C','D',])
display_side_by_side(df1,df2,df1)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 感谢您的出色解决方案!如果您想在显示数据框之前对其进行样式设置,则输入将是“Styler”,而不是“DataFrame”。在这种情况下,请使用“html_str+=df.render()”而不是“html_str+=df.to_html()”。 (2认同)
  • 由于某种原因,这在 JupyterLab 3.0.11 中不起作用。也许是因为 JupyterLab 使用与 Jupyter Classic NB 不同的客户端渲染引擎?我刚刚尝试在 Jupyter Classic NB 中运行与上面完全相同的代码,该代码是从 JupyterLab 的 v3.0.11 帮助菜单中启动的,只是为了确保所有其他变量都相同。如上图所示,完美显示。我在 Python v3.7.10 上运行 iPython 7.25.0。有趣的!我还不完全理解为什么 JupyterLab 无法渲染 HTML。有人知道为什么吗? (2认同)

zar*_*rak 67

您可以覆盖输出代码的CSS.它flex-direction: column默认使用.请尝试将其更改为row.这是一个例子:

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

CSS = """
.output {
    flex-direction: row;
}
"""

HTML('<style>{}</style>'.format(CSS))
Run Code Online (Sandbox Code Playgroud)

Jupyter图像

当然,您可以根据需要进一步自定义CSS.

如果您希望仅定位一个单元格的输出,请尝试使用:nth-child()选择器.例如,此代码将修改笔记本中仅第5个单元格的输出的CSS:

CSS = """
div.cell:nth-child(5) .output {
    flex-direction: row;
}
"""
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案会影响所有细胞,我如何只为一个细胞做这个? (4认同)
  • `HTML('<style> .output {flex-direction:row;} </ style>')`为简单起见 (3认同)
  • @jrovegno我更新了我的答案,包括您要求的信息. (2认同)
  • @ntg 您需要确保行 `HTML('&lt;style&gt;{}&lt;/style&gt;'.format(CSS))` 是单元格中的最后一行(并且不要忘记使用第 n 个子选择器)。但是,这可能会导致格式问题,因此您的解决方案更好。(+1) (2认同)
  • @zarak Thanx 的客气话:) 在您的解决方案中,您可以使用 display(HTML('&lt;style&gt;{}&lt;/style&gt;'.format(CSS))) 而不是 HTML('&lt;style&gt;{}&lt;/样式&gt;'.format(CSS)) 。然后它可以在任何地方。我仍然遇到第 n 个单元格的问题(意思是,如果我复制粘贴,n 可能会改变) (2认同)

Ant*_*bev 26

结合 gibbone(设置样式和标题)和 stevi(添加空间)的方法,我制作了我的函数版本,它将 Pandas 数据框并排输出为表格:

from IPython.core.display import display, HTML

def display_side_by_side(dfs:list, captions:list):
    """Display tables side by side to save vertical space
    Input:
        dfs: list of pandas.DataFrame
        captions: list of table captions
    """
    output = ""
    combined = dict(zip(captions, dfs))
    for caption, df in combined.items():
        output += df.style.set_table_attributes("style='display:inline'").set_caption(caption)._repr_html_()
        output += "\xa0\xa0\xa0"
    display(HTML(output))
Run Code Online (Sandbox Code Playgroud)

用法:

display_side_by_side([df1, df2, df3], ['caption1', 'caption2', 'caption3'])
Run Code Online (Sandbox Code Playgroud)

输出:

在此处输入图片说明


gib*_*one 22

pandas 0.17.1DataFrames的可视化开始可以使用pandas样式方法直接修改

要并排显示两个DataFrame,您必须使用ntg answer中建议set_table_attributes的参数.这将返回两个对象,以显示对齐的数据帧,只需通过IPython中的方法传递其连接的HTML表示:"style='display:inline'"Stylerdisplay_html

import numpy as np
import pandas as pd   
from IPython.display import display_html 

df1 = pd.DataFrame(np.arange(12).reshape((3,4)),columns=['A','B','C','D',])
df2 = pd.DataFrame(np.arange(16).reshape((4,4)),columns=['A','B','C','D',])

df1_styler = df1.style.set_table_attributes("style='display:inline'").set_caption('Caption table 1')
df2_styler = df2.style.set_table_attributes("style='display:inline'").set_caption('Caption table 2')

display_html(df1_styler._repr_html_()+df2_styler._repr_html_(), raw=True)
Run Code Online (Sandbox Code Playgroud)

对齐的数据帧pandas styler

使用此方法也更容易添加其他样式选项.以下是按照此处的要求添加标题的方法:

import numpy as np
import pandas as pd   
from IPython.display import display_html 

df1 = pd.DataFrame(np.arange(12).reshape((3,4)),columns=['A','B','C','D',])
df2 = pd.DataFrame(np.arange(16).reshape((4,4)),columns=['A','B','C','D',])

df1_styler = df1.style.set_table_attributes("style='display:inline'").set_caption('Caption table 1')
df2_styler = df2.style.set_table_attributes("style='display:inline'").set_caption('Caption table 2')

display_html(df1_styler._repr_html_()+df2_styler._repr_html_(), raw=True)
Run Code Online (Sandbox Code Playgroud)

对齐的数据帧pandas样式与标题

  • @gibbone 有没有办法指定表格之间的间距? (7认同)

Ric*_*PhD 14

在此输入图像描述这是display_side_by_side()@Anton Golubev 引入的函数的另一个变体,它结合了 gibbone (设置样式和标题)和 stevi (添加空间),我添加了一个额外的参数来在运行时更改表之间的间距。

from IPython.core.display import display, HTML

def display_side_by_side(dfs:list, captions:list, tablespacing=5):
    """Display tables side by side to save vertical space
    Input:
        dfs: list of pandas.DataFrame
        captions: list of table captions
    """
    output = ""
    for (caption, df) in zip(captions, dfs):
        output += df.style.set_table_attributes("style='display:inline'").set_caption(caption)._repr_html_()
        output += tablespacing * "\xa0"
    display(HTML(output))
    
display_side_by_side([df1, df2, df3], ['caption1', 'caption2', 'caption3'])
Run Code Online (Sandbox Code Playgroud)

tablepacing=5 默认参数值(此处显示 = 5)确定表之间的垂直间距。


Pri*_*ate 10

这是我前几天遇到的Jake Vanderplas的解决方案:

import numpy as np
import pandas as pd

class display(object):
    """Display HTML representation of multiple objects"""
    template = """<div style="float: left; padding: 10px;">
    <p style='font-family:"Courier New", Courier, monospace'>{0}</p>{1}
    </div>"""

    def __init__(self, *args):
        self.args = args

    def _repr_html_(self):
        return '\n'.join(self.template.format(a, eval(a)._repr_html_())
                     for a in self.args)

    def __repr__(self):
       return '\n\n'.join(a + '\n' + repr(eval(a))
                       for a in self.args)
Run Code Online (Sandbox Code Playgroud)

图片来源:https://github.com/jakevdp/PythonDataScienceHandbook/blob/master/notebooks/03.08-Aggregation-and-Grouping.ipynb

  • 你能解释一下这个答案吗?杰克·范德普拉斯 (Jake VanderPlas) 尚未在他的网站上对此进行解释。这是唯一在顶部打印数据集名称的解决方案。 (2认同)

MSo*_*rro 10

@zarak 代码非常小,但会影响整个笔记本的布局。其他选项对我来说有点混乱。

我在这个答案中添加了一些清晰的 CSS ,仅影响当前单元格的输出。您还可以在数据框下方或上方添加任何内容。

from ipywidgets import widgets, Layout
from IPython import display
import pandas as pd
import numpy as np

# sample data
df1 = pd.DataFrame(np.random.randn(8, 3))
df2 = pd.DataFrame(np.random.randn(8, 3))

# create output widgets
widget1 = widgets.Output()
widget2 = widgets.Output()

# render in output widgets
with widget1:
    display.display(df1.style.set_caption('First dataframe'))
    df1.info()
with widget2:
    display.display(df2.style.set_caption('Second dataframe'))
    df1.info()


# add some CSS styles to distribute free space
box_layout = Layout(display='flex',
                    flex_flow='row',
                    justify_content='space-around',
                    width='auto'
                   )
    
# create Horisontal Box container
hbox = widgets.HBox([widget1, widget2], layout=box_layout)

# render hbox
hbox
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


小智 9

我的解决方案只是在HTML中构建一个表,没有任何CSS hacks并输出它:

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

def multi_column_df_display(list_dfs, cols=3):
    html_table = "<table style='width:100%; border:0px'>{content}</table>"
    html_row = "<tr style='border:0px'>{content}</tr>"
    html_cell = "<td style='width:{width}%;vertical-align:top;border:0px'>{{content}}</td>"
    html_cell = html_cell.format(width=100/cols)

    cells = [ html_cell.format(content=df.to_html()) for df in list_dfs ]
    cells += (cols - (len(list_dfs)%cols)) * [html_cell.format(content="")] # pad
    rows = [ html_row.format(content="".join(cells[i:i+cols])) for i in range(0,len(cells),cols)]
    display(HTML(html_table.format(content="".join(rows))))

list_dfs = []
list_dfs.append( pd.DataFrame(2*[{"x":"hello"}]) )
list_dfs.append( pd.DataFrame(2*[{"x":"world"}]) )
multi_column_df_display(2*list_dfs)
Run Code Online (Sandbox Code Playgroud)

产量


Ant*_*ins 8

这会为@ nts的答案添加标题:

from IPython.display import display_html

def mydisplay(dfs, names=[]):
    html_str = ''
    if names:
        html_str += ('<tr>' + 
                     ''.join(f'<td style="text-align:center">{name}</td>' for name in names) + 
                     '</tr>')
    html_str += ('<tr>' + 
                 ''.join(f'<td style="vertical-align:top"> {df.to_html(index=False)}</td>' 
                         for df in dfs) + 
                 '</tr>')
    html_str = f'<table>{html_str}</table>'
    html_str = html_str.replace('table','table style="display:inline"')
    display_html(html_str, raw=True)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述