web-dev-qa-db-fra.com

Jupyter notebook display two pandas tables côte à côte

J'ai deux pandas dataframes et je voudrais les afficher dans le cahier Jupyter.

Faire quelque chose comme:

display(df1)
display(df2)

Leur montre les uns en dessous des autres:

enter image description here

Je voudrais avoir un deuxième dataframe à droite du premier. Il y a ne question similaire , mais il semble qu'une personne soit satisfaite de les fusionner en une seule trame de données et de montrer la différence entre elles.

Cela ne fonctionnera pas pour moi. Dans mon cas, les cadres de données peuvent représenter des éléments complètement différents (éléments non comparables) et leur taille peut être différente. Ainsi, mon objectif principal est de gagner de la place.

59
Salvador Dali

Vous pouvez remplacer le CSS du code de sortie. Il utilise flex-direction: column Par défaut. Essayez de le remplacer par row. Voici un exemple:

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

Vous pouvez bien entendu personnaliser le CSS à votre guise.

Si vous souhaitez ne cibler que la sortie d'une cellule, essayez d'utiliser le sélecteur :nth-child(). Par exemple, ce code modifiera le CSS de la sortie de la 5ème cellule du cahier uniquement:

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

J'ai fini par écrire une fonction qui peut faire ceci:

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)

Exemple d'utilisation:

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

74
ntg

Partant de pandas 0.17.1 _ la visualisation des DataFrames peut être directement modifiée avec méthodes de styling des pandas

Pour afficher deux DataFrames côte à côte, vous devez utiliser set_table_attributes avec l'argument "style='display:inline'" comme suggéré dans ntg answer . Cela retournera deux objets Styler, pour afficher les cadres de données alignés, il suffit de passer leur représentation HTML jointe via le display_html méthode d'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)

aligned dataframes pandas styler

Avec cette méthode, il est également plus facile d’ajouter d’autres options de style. Voici comment ajouter une légende, comme demandé ici :

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

15
gibbone

Voici la solution de Jake Vanderplas que je suis tombée sur l’autre jour:

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)

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

9
Private

Ma solution construit simplement un tableau en HTML sans aucun hack CSS et le sort:

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

8
Yasin Zähringer

Cela ajoute des en-têtes à la réponse de @ 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
Antony Hatchkins

J'ai fini par utiliser 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)))
1
Dinis Cruz

La réponse de Gibbone a fonctionné pour moi! Si vous voulez un espace supplémentaire entre les tables, allez au code qu'il a proposé et ajoutez ceci "\xa0\xa0\xa0" à la ligne de code suivante.

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