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:
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.
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))
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;
}
"""
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)
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)
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)
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)
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)
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)
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)))
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)