Jupyter 노트북은 두 개의 판다 테이블을 나란히 표시합니다.


96

두 개의 pandas 데이터 프레임이 있으며 Jupyter 노트북에 표시하고 싶습니다.

다음과 같이합니다.

display(df1)
display(df2)

아래에 하나씩 표시합니다.

여기에 이미지 설명 입력

첫 번째 데이터 프레임의 오른쪽에 두 번째 데이터 프레임을 갖고 싶습니다. 이 비슷한 질문이 있지만, 사람이 그들 사이의 차이를 보여주는 하나의 dataframe에서 그들을 병합하여 하나 만족이 것 같습니다.

이것은 나를 위해 작동하지 않습니다. 제 경우에는 데이터 프레임이 완전히 다른 (비교할 수없는 요소)를 나타낼 수 있으며 크기도 다를 수 있습니다. 따라서 나의 주요 목표는 공간을 절약하는 것입니다.


Jake Vanderplas의 솔루션을 게시했습니다. 멋진 깨끗한 코드.
비공개

답변:


90

출력 코드의 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 이미지

물론 원하는대로 CSS를 사용자 정의 할 수 있습니다.

한 셀의 출력 만 대상으로 지정하려면 :nth-child()선택기를 사용해보십시오 . 예를 들어,이 코드는 노트북에서 5 번째 셀의 출력 CSS를 수정합니다.

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

5
이 솔루션은 모든 셀에 영향을줍니다. 하나의 셀에만이 작업을 수행 할 수있는 방법은 무엇입니까?
jrovegno

2
@jrovegno 요청한 정보를 포함하도록 내 답변을 업데이트했습니다.
zarak

1
@ntg 줄 HTML('<style>{}</style>'.format(CSS))이 셀의 마지막 줄 인지 확인해야합니다 (n 번째 자식 선택기를 사용하는 것을 잊지 마십시오). 그러나 이로 인해 서식 지정에 문제가 발생할 수 있으므로 솔루션이 더 좋습니다. (+1)
zarak

1
@zarak Thanx for the 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

122

나는 이것을 할 수있는 함수를 작성하게되었다.

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)

여기에 이미지 설명 입력


정말 대단해요, 감사합니다. 각 출력 위에 데이터 프레임 이름을 추가하는 것이 얼마나 쉬울까요?
Ricky McMaster

1
이 두 가지 문제 될 다음 dataframes의 이름을 아는 1. 범위 이럴를 벗어 stackoverflow.com/questions/2749796/... 하지만 할 수 stackoverflow.com/questions/218616/...을 , 또는 2.) PARAMS로 전달 추가 html이 필요하며 개방형 / 무엇을해야할지 ... 여기이 부분이 어떻게 보일 수 있는지에 대한 기본 예가 있습니다. i.stack.imgur.com/mIVsD.png
ntg

답변 해 주셔서 감사합니다 . 마지막 댓글에서 설명한 것과 유사한 방식으로 헤더추가 했습니다.
Antony Hatchkins

놀라운 대답입니다. 이것이 제가 찾고있는 것이기도합니다. 나는 아직도 그것에 대해 배우는 중이므로 알고 싶습니다. 1) 왜 *args대신 사용 했 df습니까? 여러 입력을 할 수 있기 때문 *args입니까? 2) 함수의 어느 부분이 두 번째 및 후속 df를 첫 번째 df 아래가 아닌 오른쪽에 추가합니까? 그것은이다 'table style="display:inline"'부분? 다시 한 번 감사드립니다
Bowen Liu

1
훌륭한 솔루션에 감사드립니다! 데이터 프레임을 표시하기 전에 스타일을 지정하려면 입력이 Stylers가 아니라 DataFrames가됩니다. 이 경우, 사용 html_str+=df.render()대신에 html_str+=df.to_html().
Martin Becker

37

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)

캡션이있는 정렬 된 데이터 프레임 팬더 스타일러


18

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

무엇을 알고 싶으십니까?
비공개

모든 기능에 대한 설명이 될 수 있습니다 / 어떻게 작동하는지, 어떻게 호출되는지 등 ... 초보자 파이썬 프로그래머가 제대로 이해할 수 있도록합니다.
Gaurav Singhal

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)대신 dataframe 내용의. 또한 f'string '에 추가'} '기호가 있습니다.

약간 관련이 없지만 셀 출력에 대한 코드가 숨겨 지도록 함수를 수정할 수 있습니까?
alpenmilch411

1
@ alpenmilch411 "숨기기 입력"확장 참조
안토니 Hatchkins

이것에 'max_rows'를 추가하는 방법을 아십니까?
Tickon

다중 인덱스 데이터 프레임을 사용할 때 이것 역시 다중 인덱스를 잃습니다.
Parthiban Rajendran

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

Gibbone의 답변이 저에게 효과적이었습니다! 테이블 사이에 추가 공간을 원하면 그가 제안한 코드로 이동 "\xa0\xa0\xa0"하여 다음 코드 줄에 추가하십시오 .

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

2

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

테스트 출력


1

@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

여기에 이미지 설명 입력


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)

다중 인덱스 데이터 프레임에 적용될 때 다중 인덱스가 손실됩니다
Parthiban Rajendran
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.