【问题标题】:Apply CSS class to Pandas DataFrame using to_html使用 to_html 将 CSS 类应用于 Pandas DataFrame
【发布时间】:2018-11-21 07:05:02
【问题描述】:

我在使用 Pandas“to_html”方法应用“classes”参数来设置 DataFrame 样式时遇到问题。

"classes : str or list or tuple, default None 应用于生成的 html 表的 CSS 类" 来自:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_html.html

我可以像这样(例如)渲染一个样式化的 DataFrame:

df = pd.DataFrame([[1, 2], [1, 3], [4, 6]], columns=['A', 'B'])

myhtml = df.style.set_properties(**{'font-size': '11pt', 'font-family': 'Calibri','border-collapse': 'collapse','border': '1px solid black'}).render()

with open('myhtml.html','w') as f:
    f.write(myhtml)        

如何使用带有“to_html”的“classes”从 DataFrame 中设置 html 输出的样式,如下所示:

df.to_html('myhtml.html',classes=<something here>)

【问题讨论】:

  • 您希望 html 文件的外观如何?
  • 我想应用示例中“set_properties”方法中给出的相同属性。
  • 创建一个字符串"&lt;style type='text/css'&gt;" + myStyles + "&lt;/style&gt;"并将其附加到df.to_html()给出的字符串中。
  • 使用with打开文件时,不需要手动close()。当存在with作用域时,变量会被垃圾回收器销毁,文件会自动关闭。
  • 感谢@igrinis。我已经编辑了我的问题。

标签: python pandas dataframe


【解决方案1】:

Pandas 的to_html 只输出一个包含 HTML 表格标记的大字符串。 classes 参数是一个方便的处理程序,用于为&lt;table&gt; 提供一个 class 属性,该属性将在 previously created CSS 文档中对其进行样式化。因此,将to_html 合并到引用外部CSS 的更广泛的HTML 文档构建中。

有趣的是,to_html 添加了双重类 &lt;table class="dataframe mystyle"&gt;,可以在 CSS 中单独引用 .dataframe {...} .mystyle{...} 或一起引用 .dataframe.mystyle {...}。下面用随机数据进行演示。

数据

import pandas as pd
import numpy as np

pd.set_option('display.width', 1000)
pd.set_option('colheader_justify', 'center')

np.random.seed(6182018)
demo_df = pd.DataFrame({'date': np.random.choice(pd.date_range('2018-01-01', '2018-06-18', freq='D'), 50),
                        'analysis_tool': np.random.choice(['pandas', 'r', 'julia', 'sas', 'stata', 'spss'],50),              
                        'database': np.random.choice(['postgres', 'mysql', 'sqlite', 'oracle', 'sql server', 'db2'],50), 
                        'os': np.random.choice(['windows 10', 'ubuntu', 'mac os', 'android', 'ios', 'windows 7', 'debian'],50), 
                        'num1': np.random.randn(50)*100,
                        'num2': np.random.uniform(0,1,50),                   
                        'num3': np.random.randint(100, size=50),
                        'bool': np.random.choice([True, False], 50)
                       },
                        columns=['date', 'analysis_tool', 'num1', 'database', 'num2', 'os', 'num3', 'bool']
          )


print(demo_df.head(10))
#      date    analysis_tool     num1      database     num2        os      num3  bool 
# 0 2018-04-21     pandas     153.474246       mysql  0.658533         ios   74    True
# 1 2018-04-13        sas     199.461669      sqlite  0.656985   windows 7   11   False
# 2 2018-06-09      stata      12.918608      oracle  0.495707     android   25   False
# 3 2018-04-24       spss      88.562111  sql server  0.113580   windows 7   42   False
# 4 2018-05-05       spss     110.231277      oracle  0.660977  windows 10   76    True
# 5 2018-04-05        sas     -68.140295  sql server  0.346894  windows 10    0    True
# 6 2018-05-07      julia      12.874660    postgres  0.195217         ios   79    True
# 7 2018-01-22          r     189.410928       mysql  0.234815  windows 10   56   False
# 8 2018-01-12     pandas    -111.412564  sql server  0.580253      debian   30   False
# 9 2018-04-12          r      38.963967    postgres  0.266604   windows 7   46   False

CSS (另存为 df_style.css)

/* includes alternating gray and white with on-hover color */

.mystyle {
    font-size: 11pt; 
    font-family: Arial;
    border-collapse: collapse; 
    border: 1px solid silver;

}

.mystyle td, th {
    padding: 5px;
}

.mystyle tr:nth-child(even) {
    background: #E0E0E0;
}

.mystyle tr:hover {
    background: silver;
    cursor: pointer;
}

熊猫

pd.set_option('colheader_justify', 'center')   # FOR TABLE <th>

html_string = '''
<html>
  <head><title>HTML Pandas Dataframe with CSS</title></head>
  <link rel="stylesheet" type="text/css" href="df_style.css"/>
  <body>
    {table}
  </body>
</html>.
'''

# OUTPUT AN HTML FILE
with open('myhtml.html', 'w') as f:
    f.write(html_string.format(table=demo_df.to_html(classes='mystyle')))

输出

HTML (参考 df_style.css,假定在同一目录中;参见表中的类参数)

<html>
  <head><title>HTML Pandas Dataframe with CSS</title></head>
  <link rel="stylesheet" type="text/css" href="df_style.css"/>
  <body>
    <table border="1" class="dataframe mystyle">
  <thead>
    <tr style="text-align: center;">
      <th></th>
      <th>date</th>
      <th>analysis_tool</th>
      <th>num1</th>
      <th>database</th>
      <th>num2</th>
      <th>os</th>
      <th>num3</th>
      <th>bool</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>2018-04-21</td>
      <td>pandas</td>
      <td>153.474246</td>
      <td>mysql</td>
      <td>0.658533</td>
      <td>ios</td>
      <td>74</td>
      <td>True</td>
    </tr>
    <tr>
      <th>1</th>
      <td>2018-04-13</td>
      <td>sas</td>
      <td>199.461669</td>
      <td>sqlite</td>
      <td>0.656985</td>
      <td>windows 7</td>
      <td>11</td>
      <td>False</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2018-06-09</td>
      <td>stata</td>
      <td>12.918608</td>
      <td>oracle</td>
      <td>0.495707</td>
      <td>android</td>
      <td>25</td>
      <td>False</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2018-04-24</td>
      <td>spss</td>
      <td>88.562111</td>
      <td>sql server</td>
      <td>0.113580</td>
      <td>windows 7</td>
      <td>42</td>
      <td>False</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2018-05-05</td>
      <td>spss</td>
      <td>110.231277</td>
      <td>oracle</td>
      <td>0.660977</td>
      <td>windows 10</td>
      <td>76</td>
      <td>True</td>
    </tr>
    ...
  </tbody>
</table>
  </body>
</html>

【讨论】:

  • 谢谢,这很令人困惑,因为在使用带有“to_html”的类之前需要在“html_string”中引用 .css 文件。似乎应该有一种方法可以直接从参数中指定 .css 文件。
  • 我认为混淆实际上是熊猫作者将方法标记为to_html(),而实际上它是to_html_table_string()。使用此方法不会生成完整的 HTML 文档,并且 class 是在&lt;table&gt; 输出中创建的特殊属性。另外,class 不仅是为 CSS 保留的,还可以在 Javascript/JQuery 等中使用。
  • df.to_html(myhtml.html) 将生成可以在浏览器中打开的数据框的简单 html 表。那不是“完整的 html 文档”吗?
  • 不是,不是。检查页面源,您会看到&lt;html&gt;&lt;body&gt; 和其他标签丢失,即使您的浏览器呈现表格。
  • 有什么方法可以给从数据框打印的表格添加标题?
【解决方案2】:

本质上,pandas.to_html() 只是导出一个纯 HTML 表。您可以在正文中的任意位置插入表格,并通过样式部分中的 CSS 控制样式。

<html>
<head>
<style> 
  table, th, td {{font-size:10pt; border:1px solid black; border-collapse:collapse; text-align:left;}}
  th, td {{padding: 5px;}}
</style>
</head>
<body>
{
  pandas.to_html()
}
</body>
</html>

【讨论】:

  • 这个方法最适合我,因为我使用 imgkit 为 pdf 报告生成 pngs
【解决方案3】:

我发现最精确,坦率地说,最简单的方法是跳过样式、to_html() 等,并使用 df.to_dict() 方法将 DF 转换为字典。

特别是给我带来麻烦的是,在 Outlook 电子邮件中显示样式化的 pandas html,因为它无法正确呈现 pandas 产生的 CSS 混乱。

通过简单地将键/值包装在您需要的标签中,添加类等,然后将所有这些连接到一个字符串中,遍历字典并在那里生成 html。 然后将此 str 粘贴到带有预定义 css 的准备好的模板中。

为方便起见,我发现两次导出相同的 df 很有用,使用 .to_dict() 和 to_dict('index') 首先填充列,然后逐行向下工作。或者,只需列出相关列名。

dict_data = [df.to_dict(), df.to_dict('index')]

return_str = '<table><tr>'

for key in dict_data[0].keys():
    return_str = return_str + '<th class="header">' + key + '</th>'

return_str = return_str + '</tr>'

for key in dict_data[1].keys():
    return_str = return_str + '<tr><th class="index">' + key + '</th>'
    for subkey in dict_data[1][key]:
        return_str = return_str + '<td>' + dict_data[1][key][subkey] + '</td>'

return_str = return_str + '</tr></table>'

然后 return_str 进入模板。

【讨论】:

    【解决方案4】:

    我是这样做的

    为 css 代码创建一个文本文件并在此处写下您的 css 代码,例如 css_style.txt 现在将这个 txt 文件作为字符串读取到你的 python 文件中

    with open('css_style.txt', 'r') as myfile: style = myfile.read()

    现在是 HTML 代码

    """<html><head>Something Something</head>{1}<div>{0}</div></html>""".format(some_panda_dataframe.to_html,style)
    

    在我的例子中是 css_style.txt 文件

    <style>
    table {
      border-collapse: collapse;
      width: 100%;
    }
    
    th {
      text-align: center;
      padding: 8px;
    }
    
    td {
      text-align: left;
      padding: 8px;
    }
    
    tr:nth-child(even){background-color: #FFD5D5}
    
    th {
      background-color: #0000FF;
      color: white;
    }
    </style>
    

    【讨论】:

      【解决方案5】:

      添加到我早期的 to_html answer 中,新的 Pandas 1.3.0+ to_xml 可以仅使用样式表(即 CSS 和 XSLT)呈现 HTML 文档,而无需任何字符串格式。

      虽然 XSLT 会涉及到复制相同的 HTML 表格设计,但它对于用户定义的更改是开放式的。

      数据

      import pandas as pd
      import numpy as np
      
      np.random.seed(1032022)
      demo_df = pd.DataFrame({
          'date': np.random.choice(pd.date_range('2021-01-01', '2021-12-31', freq='D'), 50),
          'analysis_tool': np.random.choice(['pandas', 'r', 'julia', 'sas', 'stata', 'spss'],50),
          'num1': np.random.randn(50)*100,
          'database': np.random.choice(['postgres', 'mysql', 'sqlite', 'oracle', 'sql server', 'db2'],50),
          'num2': np.random.uniform(0,1,50),
          'os': np.random.choice(['windows 10', 'ubuntu', 'mac os', 'android', 'ios', 'windows 7', 'debian'],50),                    
          'num3': np.random.randint(100, size=50),
          'bool': np.random.choice([True, False], 50)
      })
      
      print(demo_df.head(10))
      #         date analysis_tool        num1  ...          os  num3   bool
      # 0 2021-05-02         stata   52.370960  ...  windows 10    36  False
      # 1 2021-03-16        pandas -135.411727  ...     android    74  False
      # 2 2021-12-17           sas  -56.823191  ...      debian    75  False
      # 3 2021-11-11        pandas  -32.575253  ...      debian    33  False
      # 4 2021-11-19         julia  176.464891  ...      mac os    63   True
      # 5 2021-12-30             r  -82.874595  ...      ubuntu    52   True
      # 6 2021-03-27             r   63.897578  ...     android    56  False
      # 7 2021-03-14         julia  -75.117220  ...      mac os     6  False
      # 8 2021-04-09          spss -302.664890  ...         ios    97   True
      # 9 2021-03-15          spss  -12.014122  ...         ios    27   True
      

      CSS (另存为DataFrameStyle.css)

      /* includes alternating gray and white with on-hover color */
      
      .mystyle {
          font-size: 11pt; 
          font-family: Arial;
          border-collapse: collapse; 
          border: 1px solid silver;
      
      }
      
      .mystyle td, th {
          padding: 5px;
      }
      
      .mystyle tr:nth-child(even) {
          background: #E0E0E0;
      }
      
      .mystyle tr:hover {
          background: silver;
          cursor: pointer;
      }
      

      XSLT (另存为 DataFrameStyle.xsl;引用 .css)

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:output method="html" omit-xml-declaration="no" indent="yes"/>
      
          <xsl:template match="/data">
            <html>
              <head><title>HTML Pandas Dataframe with CSS</title></head>
              <link rel="stylesheet" type="text/css" href="DataFrameStyle.css"/>
              <body>
                <table border="1" class="dataframe mystyle">
                  <thead>
                      <tr style="text-align: center;">
                          <xsl:apply-templates select="row[1]/*" mode="headers"/>
                      </tr>
                  </thead>
                  <tbody>
                      <xsl:apply-templates select="row"/>
                  </tbody>
                </table>
              </body>
            </html>
          </xsl:template>
      
          <xsl:template match="row[1]/*" mode="headers">
              <th><xsl:value-of select="local-name()"/></th>
          </xsl:template>
      
          <xsl:template match="row">
              <tr><xsl:apply-templates select="*"/></tr>
          </xsl:template>
          
          <xsl:template match="row/*">
             <td><xsl:value-of select="."/></td>
          </xsl:template>
      
      </xsl:stylesheet>
      

      熊猫

      demo_df.to_xml(
          "/path/to/Output.html",
          stylesheet = "DataFrameStyle.xsl"
      )
      

      输出

      【讨论】:

        猜你喜欢
        • 2020-05-09
        • 2019-02-06
        • 2018-11-23
        • 2017-07-26
        • 2016-08-22
        • 2019-04-10
        • 2020-12-24
        • 2019-01-02
        • 2019-12-25
        相关资源
        最近更新 更多