复制 Jupyter Notebook Pandas 数据帧 HTML 打印输出 [英] Replicating Jupyter Notebook Pandas dataframe HTML printout

查看:46
本文介绍了复制 Jupyter Notebook Pandas 数据帧 HTML 打印输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 jupyter 在其笔记本中用于 Pandas 数据帧的输出复制到 html/css/js,以便 Flask jsonify 可以将其返回为 html,稍后我将在 AJAX 中使用它称呼.

我发现

...但是当我们输出 HTML 文件时它仍然很漂亮吗??是的.你可以做一些更多的 CSS 样式来让它恰到好处(字体大小、字体系列、文本装饰、边距/填充等),但这给了你一个开始.见下文:

print(html.render())

<style type="text/css" >#T_3e73cfd2_396c_11e8_9d70_240a645b34fc {边距:0;font-family: "Helvetica", "Arial", sans-serif;边框折叠:折叠;边界:无;边框:2px 实心 #ccf;} #T_3e73cfd2_396c_11e8_9d70_240a645b34fc 头{背景颜色:#cc8484;} #T_3e73cfd2_396c_11e8_9d70_240a645b34fc tbody tr:nth-child(even) {背景色:#fff;} #T_3e73cfd2_396c_11e8_9d70_240a645b34fc tbody tr:nth-child(odd) {背景色:#eee;} #T_3e73cfd2_396c_11e8_9d70_240a645b34fc td {填充:.5em;} #T_3e73cfd2_396c_11e8_9d70_240a645b34fc th {字体大小:125%;文本对齐:居中;} #T_3e73cfd2_396c_11e8_9d70_240a645b34fc 标题{字幕侧:底部;} #T_3e73cfd2_396c_11e8_9d70_240a645b34fc tbody tr:hover {背景色:#add8e6;}</风格><table id="T_3e73cfd2_396c_11e8_9d70_240a645b34fc" ><caption>悬停以突出显示.</caption><头><tr><th class="blank" ></th><th class="blank level0" ></th><th class="col_heading level0 col0" >0</th></tr><tr><th class="index_name level0" >first</th><th class="index_name level1" >second</th><th class="blank" ></th></tr></thead><tr><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel0_row0" class="row_heading level0 row0" rowspan=2>bar</th><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row0" class="row_heading level1 row0" >one</th><td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow0_col0" class="data row0 col0" >-0.130634</td></tr><tr><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row1" class="row_heading level1 row1" >二</th><td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow1_col0" class="data row1 col0" >1.17685</td></tr><tr><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel0_row2" class="row_heading level0 row2" rowspan=2>baz</th><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row2" class="row_heading level1 row2" >one</th><td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow2_col0" class="data row2 col0" >0.500367</td></tr><tr><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row3" class="row_heading level1 row3" >二</th><td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow3_col0" class="data row3 col0" >0.555932</td></tr><tr><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel0_row4" class="row_heading level0 row4" rowspan=2>foo</th><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row4" class="row_heading level1 row4" >one</th><td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow4_col0" class="data row4 col0" >-0.744553</td></tr><tr><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row5" class="row_heading level1 row5" >二</th><td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow5_col0" class="data row5 col0" >-1.41269</td></tr><tr><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel0_row6" class="row_heading level0 row6" rowspan=2>qux</th><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row6" class="row_heading level1 row6" >one</th><td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow6_col0" class="data row6 col0" >0.726728</td></tr><tr><th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row7" class="row_heading level1 row7" >二</th><td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow7_col0" class="data row7 col0" >-0.683555</td></tr></tbody>

I'm trying to replicate the output that jupyter uses for a pandas dataframe in their notebooks to html/css/js so that it's returnable by Flask jsonify as html that I later use in an AJAX call.

I found this, and this, which suggested using the pandas builtin style functionality rather than CSS hacks but i'm struggling to get the desired functionality:

def hover(hover_color="#add8e6"):
    return dict(selector="tr:hover",
                props=[("background-color", "%s" % hover_color)])

styles = [
    hover(),
    dict(selector="th", props=[("font-size", "125%"),
                               ("text-align", "center"),
                               ("padding", "5px 5px")]),
    dict(selector="tr", props=[("text-align", "center")]),
    dict(selector="caption", props=[("caption-side", "bottom")])
]

# creating some dummy data
index = pd.MultiIndex(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
                      labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
                      names=['first', 'second'])

df = pd.DataFrame(data=np.random.randn(8), index=index)

# you'll see the html rendered bellow
df.style.set_table_styles(styles).set_caption("test").render()

Compared to jupyter notebooks, this is missing some default background color stripping, and the header shouldn't apply the hover class. The only way I can think to apply something on select elements would be to add class= or id= but the style functionality hides all that.

<style  type="text/css" >     #T_479b61ba_292a_11e8_86bf_0ee09a5428a2 tr:hover {           background-color: #add8e6;     }    #T_479b61ba_292a_11e8_86bf_0ee09a5428a2 th {           font-size: 150%;           text-align: center;     }    #T_479b61ba_292a_11e8_86bf_0ee09a5428a2 caption {           caption-side: bottom;     }</style>   <table id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2" ><caption>Hover to highlight.</caption>  <thead>    <tr>          <th class="blank" ></th>          <th class="blank level0" ></th>          <th class="col_heading level0 col0" >0</th>      </tr>    <tr>          <th class="index_name level0" >first</th>          <th class="index_name level1" >second</th>          <th class="blank" ></th>      </tr></thead>  <tbody>    <tr>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level0_row0" class="row_heading level0 row0" rowspan=2>bar</th>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level1_row0" class="row_heading level1 row0" >one</th>          <td id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2row0_col0" class="data row0 col0" >-0.0690895</td>      </tr>    <tr>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level1_row1" class="row_heading level1 row1" >two</th>          <td id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2row1_col0" class="data row1 col0" >-0.518092</td>      </tr>    <tr>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level0_row2" class="row_heading level0 row2" rowspan=2>baz</th>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level1_row2" class="row_heading level1 row2" >one</th>          <td id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2row2_col0" class="data row2 col0" >-0.163842</td>      </tr>    <tr>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level1_row3" class="row_heading level1 row3" >two</th>          <td id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2row3_col0" class="data row3 col0" >-0.144757</td>      </tr>    <tr>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level0_row4" class="row_heading level0 row4" rowspan=2>foo</th>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level1_row4" class="row_heading level1 row4" >one</th>          <td id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2row4_col0" class="data row4 col0" >1.22865</td>      </tr>    <tr>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level1_row5" class="row_heading level1 row5" >two</th>          <td id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2row5_col0" class="data row5 col0" >1.83947</td>      </tr>    <tr>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level0_row6" class="row_heading level0 row6" rowspan=2>qux</th>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level1_row6" class="row_heading level1 row6" >one</th>          <td id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2row6_col0" class="data row6 col0" >0.793328</td>      </tr>    <tr>          <th id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2level1_row7" class="row_heading level1 row7" >two</th>          <td id="T_479b61ba_292a_11e8_86bf_0ee09a5428a2row7_col0" class="data row7 col0" >-0.723836</td>      </tr></tbody>  </table> 

解决方案

I've made a few changes to your code to get the functionality you want:

  • Pandas dataframes are styled with two special HTML tags for tables, namely thead for the header and tbody for the body. We can use this to specify the highlighting behavior as body-only
  • CSS has "even" and "odd" properties which you can use to add shading effects to tables.
  • In order for hover to work with the background shading specified, it must be called last not first

In Jupyter Notebook:

import pandas as pd
import numpy as np
from IPython.display import HTML

def hover(hover_color="#add8e6"):
    return dict(selector="tbody tr:hover",
            props=[("background-color", "%s" % hover_color)])

styles = [
    #table properties
    dict(selector=" ", 
         props=[("margin","0"),
                ("font-family",'"Helvetica", "Arial", sans-serif'),
                ("border-collapse", "collapse"),
                ("border","none"),
                ("border", "2px solid #ccf")
                   ]),

    #header color - optional
    dict(selector="thead", 
         props=[("background-color","#cc8484")
               ]),

    #background shading
    dict(selector="tbody tr:nth-child(even)",
         props=[("background-color", "#fff")]),
    dict(selector="tbody tr:nth-child(odd)",
         props=[("background-color", "#eee")]),

    #cell spacing
    dict(selector="td", 
         props=[("padding", ".5em")]),

    #header cell properties
    dict(selector="th", 
         props=[("font-size", "125%"),
                ("text-align", "center")]),

    #caption placement
    dict(selector="caption", 
         props=[("caption-side", "bottom")]),

    #render hover last to override background-color
    hover()
]
html = (df.style.set_table_styles(styles)
      .set_caption("Hover to highlight."))
html

...but is it still beautiful when we output the HTML file?? Yes. You can do some more CSS styling to get it just right (font-size, font-family, text-decoration, margin/padding, etc) but this gives you a start. See below:

print(html.render())

<style  type="text/css" >
    #T_3e73cfd2_396c_11e8_9d70_240a645b34fc   {
          margin: 0;
          font-family: "Helvetica", "Arial", sans-serif;
          border-collapse: collapse;
          border: none;
          border: 2px solid #ccf;
    }    #T_3e73cfd2_396c_11e8_9d70_240a645b34fc thead {
          background-color: #cc8484;
    }    #T_3e73cfd2_396c_11e8_9d70_240a645b34fc tbody tr:nth-child(even) {
          background-color: #fff;
    }    #T_3e73cfd2_396c_11e8_9d70_240a645b34fc tbody tr:nth-child(odd) {
          background-color: #eee;
    }    #T_3e73cfd2_396c_11e8_9d70_240a645b34fc td {
          padding: .5em;
    }    #T_3e73cfd2_396c_11e8_9d70_240a645b34fc th {
          font-size: 125%;
          text-align: center;
    }    #T_3e73cfd2_396c_11e8_9d70_240a645b34fc caption {
          caption-side: bottom;
    }    #T_3e73cfd2_396c_11e8_9d70_240a645b34fc tbody tr:hover {
          background-color: #add8e6;
    }</style>  
<table id="T_3e73cfd2_396c_11e8_9d70_240a645b34fc" ><caption>Hover to highlight.</caption> 
<thead>    <tr> 
        <th class="blank" ></th> 
        <th class="blank level0" ></th> 
        <th class="col_heading level0 col0" >0</th> 
    </tr>    <tr> 
        <th class="index_name level0" >first</th> 
        <th class="index_name level1" >second</th> 
        <th class="blank" ></th> 
    </tr></thead> 
<tbody>    <tr> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel0_row0" class="row_heading level0 row0" rowspan=2>bar</th> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row0" class="row_heading level1 row0" >one</th> 
        <td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow0_col0" class="data row0 col0" >-0.130634</td> 
    </tr>    <tr> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row1" class="row_heading level1 row1" >two</th> 
        <td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow1_col0" class="data row1 col0" >1.17685</td> 
    </tr>    <tr> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel0_row2" class="row_heading level0 row2" rowspan=2>baz</th> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row2" class="row_heading level1 row2" >one</th> 
        <td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow2_col0" class="data row2 col0" >0.500367</td> 
    </tr>    <tr> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row3" class="row_heading level1 row3" >two</th> 
        <td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow3_col0" class="data row3 col0" >0.555932</td> 
    </tr>    <tr> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel0_row4" class="row_heading level0 row4" rowspan=2>foo</th> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row4" class="row_heading level1 row4" >one</th> 
        <td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow4_col0" class="data row4 col0" >-0.744553</td> 
    </tr>    <tr> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row5" class="row_heading level1 row5" >two</th> 
        <td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow5_col0" class="data row5 col0" >-1.41269</td> 
    </tr>    <tr> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel0_row6" class="row_heading level0 row6" rowspan=2>qux</th> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row6" class="row_heading level1 row6" >one</th> 
        <td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow6_col0" class="data row6 col0" >0.726728</td> 
    </tr>    <tr> 
        <th id="T_3e73cfd2_396c_11e8_9d70_240a645b34fclevel1_row7" class="row_heading level1 row7" >two</th> 
        <td id="T_3e73cfd2_396c_11e8_9d70_240a645b34fcrow7_col0" class="data row7 col0" >-0.683555</td> 
    </tr></tbody> 
</table> 

这篇关于复制 Jupyter Notebook Pandas 数据帧 HTML 打印输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆