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

时间:2016-08-05 06:58:08

标签: pandas ipython-notebook jupyter-notebook

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

做类似的事情:

display(df1)
display(df2)

将它们显示在另一个之下:

enter image description here

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

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

13 个答案:

答案 0 :(得分:66)

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

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)

使用示例:

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

答案 1 :(得分:51)

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

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

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

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

答案 2 :(得分:10)

pandas 0.17.1开始,可以使用pandas styling methods

直接修改DataFrame的可视化

要并排显示两个DataFrame,您必须使用set_table_attributes"style='display:inline'"建议参数Styler。这将返回两个display_html个对象, 显示对齐的数据帧只需通过IPython中的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('Table 1') df2_styler = df2.style.set_table_attributes("style='display:inline'").set_caption('Table 2') display_html(df1_styler._repr_html_()+df2_styler._repr_html_(), raw=True) 方法传递其连接的HTML表示:

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)

ntg answer

使用此方法也更容易添加其他样式选项。以下是按要求添加标题的方法aligned dataframes pandas styler

setInterval

here

答案 3 :(得分:9)

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

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

答案 4 :(得分:7)

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

答案 5 :(得分:6)

这会在@ 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

答案 6 :(得分:5)

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

用法:

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

输出:

enter image description here

答案 7 :(得分:2)

长臂猿的答案对我有用!如果要在表之间留出更多空间,请转到他建议的代码,然后将此"\xa0\xa0\xa0"添加到以下代码行。

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

答案 8 :(得分:2)

我决定在Yasin的优雅答案中添加一些额外的功能,在其中可以选择行的列数;然后将所有多余的df添加到底部。 另外,可以选择填充网格的顺序(只需根据需要将填充关键字更改为“ 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

答案 9 :(得分:1)

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

我已为此answer添加了一些清晰的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

enter image description here

答案 10 :(得分:0)

我最终使用了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)))

答案 11 :(得分:0)

antony答案的扩展如果要将表格的可视化限制为每行一些块,请使用maxTables变量。enter image description here

def mydisplay(dfs, names=[]):

    count = 0
    maxTables = 6

    if not names:
        names = [x for x in range(len(dfs))]

    html_str = ''
    html_th = ''
    html_td = ''

    for df, name in zip(dfs, names):
        if count <= (maxTables):
            html_th += (''.join(f'<th style="text-align:center">{name}</th>'))
            html_td += (''.join(f'<td style="vertical-align:top"> {df.to_html(index=False)}</td>'))
            count += 1
        else:
            html_str += f'<tr>{html_th}</tr><tr>{html_td}</tr>'
            html_th = f'<th style="text-align:center">{name}</th>'
            html_td = f'<td style="vertical-align:top"> {df.to_html(index=False)}</td>'
            count = 0


    if count != 0:
        html_str += f'<tr>{html_th}</tr><tr>{html_td}</tr>'


    html_str += f'<table>{html_str}</table>'
    html_str = html_str.replace('table','table style="display:inline"')
    display_html(html_str, raw=True)

答案 12 :(得分:0)

enter image description here这是@Anton Golubev 引入的 display_side_by_side() 函数的另一个变体,它结合了长臂猿(设置样式和标题)和 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 = ""
    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 += tablespacing * "\xa0"
    display(HTML(output))
    
display_side_by_side([df1, df2, df3], ['caption1', 'caption2', 'caption3'])

tablespacing=5 默认参数值(此处显示为 5)决定了表格之间的垂直间距。