Jupyter Notebookに2つのパンダテーブルが並べて表示されています


94

2つのパンダデータフレームがあり、それらをJupyter Notebookに表示したいと思います。

次のようなことをする:

display(df1)
display(df2)

それらを上下に表示します。

ここに画像の説明を入力してください

最初のデータフレームの右側に2番目のデータフレームを配置したいと思います。同様の質問がありますが 1つのデータフレームにそれらをマージして、両者の違いを示すことで、人は満足しているようです。

これは私にはうまくいきません。私の場合、データフレームは完全に異なる(比較不可能な要素)場合があり、それらのサイズは異なる場合があります。したがって、私の主な目標はスペースを節約することです。


Jake Vanderplasのソリューションを投稿しました。きれいなコード。
プライベート

回答:


85

出力コードの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))

ジュピター画像

もちろん、必要に応じてCSSをさらにカスタマイズすることもできます。

1つのセルの出力のみをターゲットにする場合は、:nth-child()セレクターを使用してみてください。たとえば、次のコードはノートブックの5番目のセルのみの出力のCSSを変更します。

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

5
このソリューションはすべてのセルに影響しますが、1つのセルに対してのみこれを行うにはどうすればよいですか?
jrovegno 2017年

2
@jrovegno回答を更新して、リクエストした情報を含めました。
zarak

1
@ntg行HTML('<style>{}</style>'.format(CSS))がセルの最後の行であることを確認する必要があります(n番目の子セレクターを使用することを忘れないでください)。ただし、これによりフォーマットに問題が発生する可能性があるため、ソリューションの方が優れています。(+1)
zarak

1
@zarak Thanx for a kind words :)ソリューションでは、HTML( '<style> {} </の代わりにdisplay(HTML(' <style> {} </ style> '。format(CSS)))を使用できますstyle> '。format(CSS))。次に、それはどこにでも置くことができます。私はまだn番目のセルに問題がありました(つまり、貼り付けをコピーすると、nが変わる可能性があります)
ntg

4
HTML('<style>.output {flex-direction: row;}</style>')簡潔にするために
Thomas Matthew

114

私はこれを行うことができる関数を書いてしまいました:

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)

ここに画像の説明を入力してください


これは本当に素晴らしいです、ありがとう。各出力の上にデータフレーム名を追加するのはどのくらい簡単か、そうでなければ簡単でしょうか。
リッキーマクマスター

1
そこの二つの問題のようになります。データフレームの名前を知っている1.スコープの私見の外にあるstackoverflow.com/questions/2749796/...なく、行うことができますstackoverflow.com/questions/218616/...を、または2.)のparamsとして渡します追加のhtmlとそのオープンエンド/アップが必要です。これは、この部分がどのように見えるかの基本的な例です。i.stack.imgur.com
ntg

回答ありがとうございます。前回のコメントで説明したのと同様の方法でヘッダー追加しました。
アントニーハッチキンズ

すばらしい答え。これも私が探しているものです。私はまだそれを回避する方法を学んでいるので、知りたいです:1)なぜあなた*argsは単にではなく代わりに使用しましたdfか?あなたは複数の入力を持つことができるからです*argsか?2)関数のどの部分で、2番目以降のdfを最初の関数の右側ではなく、右側に追加しますか?それは'table style="display:inline"'一部?ありがとうございました
Bowen Liu

1
あなたの素晴らしい解決策をありがとう!データフレームを表示する前にスタイルを設定する場合、入力はStylersではなくDataFramesになります。この場合、のhtml_str+=df.render()代わりにを使用してくださいhtml_str+=df.to_html()
Martin Becker、

35

pandas 0.17.1データフレームの視覚化から始めて、パンダのスタイリング方法で直接変更できます

2つのDataFrameを並べて表示するset_table_attributesには"style='display:inline'"ntg answerで提案されている引数を使用する必要があります。これは2つのStylerオブジェクトを返します。整列されたデータフレームを表示するには、結合されたHTML表現をdisplay_htmlIPython のメソッドを介して渡します。

この方法では、他のスタイルオプションを追加するのも簡単です。ここで要求されたように、キャプションを追加する方法は次のとおりです

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)

キャプション付きの整列したデータフレームパンダスタイラー


15

gibbone(スタイルとキャプションを設定する)とstevi(スペースを追加する)のアプローチを組み合わせて、パンダデータフレームをテーブルとして並べて出力する関数のバージョンを作成しました。

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'])

出力:

ここに画像の説明を入力してください


11

先日私が遭遇した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


1
この答えを説明してください。Jake VanderPlasは彼のウェブサイトでそれを説明していません。これは、データセット名を上部に出力する唯一のソリューションです。
Gaurav Singhal

何が知りたいですか?
プライベート

すべての関数/それらがどのように機能するか、どのように呼ばれるかなどの説明かもしれません...初心者のpythonプログラマが正しく理解できるようにするためです。
Gaurav Singhal、2018年

10

私のソリューションは、CSSをハックせずにHTMLでテーブルを作成し、それを出力するだけです。

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)

出力


9

これにより、@ 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)

ここに画像の説明を入力してください


これは非常に便利に見えますが、問題があります。以下のためにmydisplay((df1,df2))のみ与えられるdf.to_html(index=False) df.to_html(index=False)代わりに、データフレームの内容の。また、f'string 'に余分な'} '記号があります。

やや無関係ですが、セル出力のコードが非表示になるように関数を変更することは可能ですか?
alpenmilch411 2018

1
@ alpenmilch411は、「Hide Input」拡張機能を参照してください
Antony Hatchkins 2018

これに「max_rows」を追加する方法はありますか?
Tickon

2

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

2

ギボンの答えは私のために働いた!テーブル間に余分なスペースが必要な場合は、彼が提案したコードに移動し、これ"\xa0\xa0\xa0"を次のコード行に追加します。

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

2

列数行数の両方を選択できるYasinのエレガントな回答にいくつかの機能を追加することにしました。次に、追加のdfが下部に追加されます。さらに、グリッドを埋める順序を選択できます(必要に応じて、fillキーワードを「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)

テスト出力


0

アントニーの答えの拡張テーブルの視覚化を行ごとのブロック数に制限する場合は、maxTables変数を使用します。ここに画像の説明を入力してください

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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.