Два ноутбука Jupyter отображают две таблицы pandas

У меня есть два фрейма pandas, и я хотел бы отображать их в ноутбуке Jupyter.

Выполнение чего-то вроде:

display(df1)
display(df2)

Показывает их ниже:

введите описание изображения здесь

Я хотел бы иметь второй фрейм данных справа от первого. Существует аналогичный вопрос, но похоже, что человек удовлетворен либо слиянием их в одном кадре данных, чтобы показать разницу между ними.

Это не сработает для меня. В моем случае dataframes могут представлять совершенно разные (несопоставимые элементы), и их размер может быть различным. Таким образом, моя главная цель - сэкономить место.

Ответ 1

Вы можете переопределить 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(). Например, этот код изменит CSS вывода только 5-й ячейки в записной книжке:

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

Ответ 2

В итоге я написал функцию, которая может это сделать:

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)

введите описание изображения здесь

Ответ 3

Начиная с pandas 0.17.1 визуализация DataFrames может быть напрямую изменена с помощью методов стилевого оформления pandas

Чтобы отобразить два DataFrames рядом, вы должны использовать set_table_attributes с аргументом "style='display:inline'", как предложено в ntg answer. Это вернет два объекта Styler. Чтобы отобразить выровненные кадры данных, просто передайте их объединенное представление HTML через метод 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('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

Ответ 4

Вот решение Джейка Вандерпласа, с которым я столкнулся на днях:

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

Ответ 5

Мое решение просто строит таблицу в HTML без хакеров CSS и выводит ее:

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

Ответ 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

Ответ 7

Комбинируя подходы 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

Ответ 8

Гиббонский ответ сработал для меня! Если вам нужно дополнительное пространство между таблицами, перейдите к предложенному им коду и добавьте этот "\xa0\xa0\xa0" в следующую строку кода.

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

Ответ 9

Я закончил с использованием 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)))