Jupyter 笔记本并排显示两个 Pandas 表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38783027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 15:44:16  来源:igfitidea点击:

Jupyter notebook display two pandas tables side by side

pandasipython-notebookjupyter-notebook

提问by Salvador Dali

I have two pandas dataframes and I would like to display them in Jupyter notebook.

我有两个熊猫数据框,我想在 Jupyter 笔记本中显示它们。

Doing something like:

做类似的事情:

display(df1)
display(df2)

Shows them one below another:

显示它们一个在另一个下面:

enter image description here

在此处输入图片说明

I would like to have a second dataframe on the right of the first one. There is a similar question, but it looks like there a person is satisfied either with merging them in one dataframe of showing the difference between them.

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

This will not work for me. In my case dataframes can represent completely different (non-comparable elements) and the size of them can be different. Thus my main goal is to save space.

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

采纳答案by zarak

You could override the CSS of the output code. It uses flex-direction: columnby default. Try changing it to rowinstead. Here's an example:

您可以覆盖输出代码的 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))

Jupyter image

Jupyter 图像

You could, of course, customize the CSS further as you wish.

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

If you wish to target only one cell's output, try using the :nth-child()selector. For example, this code will modify the CSS of the output of only the 5th cell in the notebook:

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

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

回答by ntg

I have ended up writing a function that can do this:

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

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)

Example usage:

用法示例:

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)

enter image description here

在此处输入图片说明

回答by gibbone

Starting from pandas 0.17.1the visualization of DataFrames can be directly modified with pandas styling methods

pandas 0.17.1DataFrame的可视化入手,可以直接用pandas的样式方法修改

To display two DataFrames side by side you must use set_table_attributeswith the argument "style='display:inline'"as suggested in ntg answer. This will return two Stylerobjects. To display the aligned dataframes just pass their joined HTML representation through the display_htmlmethod from IPython.

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

With this method is also easier to add other styling options. Here's how to add a caption, as requested here:

使用此方法还可以更轻松地添加其他样式选项。以下是根据此处的要求添加标题的方法:

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)

aligned dataframes pandas styler with caption

与标题对齐的数据框熊猫造型器

回答by Anton Golubev

Combining approaches of gibbone (to set styles and captions) and stevi (adding space) I made my version of function, which outputs pandas dataframes as tables side-by-side:

结合 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))

Usage:

用法:

display_side_by_side([df1, df2, df3], ['caption1', 'caption2', 'caption3'])

Output:

输出:

enter image description here

在此处输入图片说明

回答by Private

Here is Jake Vanderplas' solution I came across just the other day:

这是我前几天遇到的 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)

Credit: https://github.com/jakevdp/PythonDataScienceHandbook/blob/master/notebooks/03.08-Aggregation-and-Grouping.ipynb

信用:https: //github.com/jakevdp/PythonDataScienceHandbook/blob/master/notebooks/03.08-Aggregation-and-Grouping.ipynb

回答by Yasin Z?hringer

My solution just builds a table in HTML without any CSS hacks and outputs it:

我的解决方案只是在 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)

Output

输出

回答by Antony Hatchkins

This adds headers to @nts's answer:

这将标题添加到@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)

enter image description here

在此处输入图片说明

回答by Dinis Cruz

I ended up using HBOX

我最终使用了 HBOX

import ipywidgets as ipyw

def get_html_table(target_df, title):
    df_style = target_df.style.set_table_attributes("style='border:2px solid;font-size:10px;margin:10px'").set_caption(title)
    return df_style._repr_html_()

df_2_html_table = get_html_table(df_2, 'Data from Google Sheet')
df_4_html_table = get_html_table(df_4, 'Data from Jira')
ipyw.HBox((ipyw.HTML(df_2_html_table),ipyw.HTML(df_4_html_table)))

回答by stevi

Gibbone's answer worked for me! If you want extra space between the tables go to the code he proposed and add this "\xa0\xa0\xa0"to the following code line.

吉本的回答对我有用!如果您想要表格之间的额外空间,请转到他建议的代码并将其添加"\xa0\xa0\xa0"到以下代码行中。

display_html(df1_styler._repr_html_()+"\xa0\xa0\xa0"+df2_styler._repr_html_(), raw=True)

回答by Martino Schr?der

I decided to add some extra functionality to Yasin's elegant answer, where one can choose both the number of cols androws; any extra dfs are then added to the bottom. Additionally one can choose in which order to fill the grid (simply change fill keyword to 'cols' or 'rows' as needed)

我决定为 Yasin 的优雅答案添加一些额外的功能,您可以在其中选择列数行数;然后将任何额外的 dfs 添加到底部。另外可以选择填充网格的顺序(只需根据需要将填充关键字更改为“cols”或“rows”)

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

def grid_df_display(list_dfs, rows = 2, cols=3, fill = 'cols'):
    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[:rows*cols] ]
    cells += cols * [html_cell.format(content="")] # pad

    if fill == 'rows': #fill in rows first (first row: 0,1,2,... col-1)
        grid = [ html_row.format(content="".join(cells[i:i+cols])) for i in range(0,rows*cols,cols)]

    if fill == 'cols': #fill columns first (first column: 0,1,2,..., rows-1)
        grid = [ html_row.format(content="".join(cells[i:rows*cols:rows])) for i in range(0,rows)]

    display(HTML(html_table.format(content="".join(grid))))

    #add extra dfs to bottom
    [display(list_dfs[i]) for i in range(rows*cols,len(list_dfs))]

list_dfs = []
list_dfs.extend((pd.DataFrame(2*[{"x":"hello"}]), 
             pd.DataFrame(2*[{"x":"world"}]), 
             pd.DataFrame(2*[{"x":"gdbye"}])))

grid_df_display(3*list_dfs)

test output

测试输出