【问题标题】:Combine index header row and column header row in Pandas在 Pandas 中合并索引标题行和列标题行
【发布时间】:2020-04-24 06:31:09
【问题描述】:

我创建一个数据框并导出到一个 html 表。但是标题如下所示

如何合并索引名行和列名行?

我希望表格标题看起来像这样:

但它目前像这样导出到 html:

我创建如下数据框(示例):

data = [{'Name': 'A', 'status': 'ok', 'host': '1', 'time1': '2020-01-06 06:31:06', 'time2': '2020-02-06 21:10:00'}, {'Name': 'A', 'status': 'ok', 'host': '2', 'time1': '2020-01-06 06:31:06', 'time2': '-'}, {'Name': 'B', 'status': 'Alert', 'host': '1', 'time1': '2020-01-06 10:31:06', 'time2': '2020-02-06 21:10:00'}, {'Name': 'B', 'status': 'ok', 'host': '2', 'time1': '2020-01-06 10:31:06', 'time2': '2020-02-06 21:10:00'},{'Name': 'B', 'status': 'ok', 'host': '4', 'time1': '2020-01-06 10:31:06', 'time2': '2020-02-06 21:10:00'},{'Name': 'C', 'status': 'Alert', 'host': '2', 'time1': '2020-01-06 10:31:06', 'time2': '2020-02-06 21:10:00'},{'Name': 'C', 'status': 'ok', 'host': '3', 'time1': '2020-01-06 10:31:06', 'time2': '2020-02-06 21:10:00'},{'Name': 'C', 'status': 'ok', 'host': '4', 'time1': '-', 'time2': '-'}]

df = pandas.DataFrame(data)
df.set_index(['Name', 'status', 'host'], inplace=True)
html_body = df.to_html(bold_rows=False)

索引设置为分层行,以便在 html 表中阅读:

print(df)

                               time1                time2
Name status host                                          
A    ok     1     2020-01-06 06:31:06  2020-02-06 21:10:00
            2     2020-01-06 06:31:06                    -
B    Alert  1     2020-01-06 10:31:06  2020-02-06 21:10:00
     ok     2     2020-01-06 10:31:06  2020-02-06 21:10:00
            4     2020-01-06 10:31:06  2020-02-06 21:10:00
C    Alert  2     2020-01-06 10:31:06  2020-02-06 21:10:00
     ok     3     2020-01-06 10:31:06  2020-02-06 21:10:00
            4                       -                    -

我唯一的解决方案是将每一列设置为索引。 这似乎不切实际,并留下一个必须手动删除的空行:

【问题讨论】:

  • df.reset_index().to_html(index=False, bold_rows=False)
  • @piRSquared - reset_index() 将删除索引。即不再合并我想要的前 2 行中的重复值。输出的html表需要可读
  • 确实如此。但这是因为 Pandas 对 MultiIndex 这样做的。您想要避免的列的错开正在发生,因为您想要“合并”的“列”实际上是 MultiIndex 的级别。因此,您可能需要自己解析对象并制作自己的 html 表。或者您可以破解您已经获得的结果 html。
  • df.reset_index() 不会改变 df 本身。它返回一个新的数据帧,换句话说,一个用于.to_html 调用的一次性变量

标签: pandas python-3.6


【解决方案1】:

设置

import pandas as pd
from IPython.display import HTML

l0 = ('Foo', 'Bar')
l1 = ('One', 'Two')
ix = pd.MultiIndex.from_product([l0, l1], names=('L0', 'L1'))
df = pd.DataFrame(1, ix, [*'WXYZ'])

HTML(df.to_html())


美人汤

破解来自df.to_html(header=False) 的HTML 结果。把表头的空单元格取出来,放入列名。

from bs4 import BeautifulSoup

html_doc = df.to_html(header=False)
soup = BeautifulSoup(html_doc, 'html.parser')

empty_cols = soup.find('thead').find_all(lambda tag: not tag.contents)

for tag, col in zip(empty_cols, df):
    tag.string = col

HTML(soup.decode_contents())

【讨论】:

  • 所以标题“修复”不是 Pandas 可以做的,甚至不关心吗?这很公平,我将在脚本中使用 BeautifulSoup 对上述内容进行测试:)
  • 这对我来说或多或少是完美的,将为我修复几张桌子,谢谢!最后一个问题是 zip(empty_cols, df) 在 for 循环中做了什么?我可以看到empty_cols 引用了任何传递给汤对象的空列标题,zip() 方法如何为这些选择正确的列名?
  • 如何在数据框 html 表中为 行索引列(最左边的列)设置标题名称?
  • 这完全是一个不同的问题。看方法rename_axis
  • 我不知道如何或为什么,但我需要使用 tag.string = str(col) 而不是 col。只是觉得这可能对任何人都有帮助。
【解决方案2】:

如果您想使用 Dataframe Styler 对您的表格、元素和内容执行 lot of wonderful formatting,那么您可能需要像我一样对 piRSquared 的答案稍作更改。

before transformation

style.to_html() 添加了不间断的空格,这使得 tag.contents 始终返回 true,因此不会对表产生任何更改。我修改了 lambda 来解决这个问题,这揭示了另一个问题。

lambda tag: (not tag.contents) or '\xa0' in tag.contents

Cells were copied strangely

Styler.to_html() 缺少标头 kwarg - 我猜这是问题的根源。我采取了一种稍微不同的方法 - 将第二行标题移到第一行,然后销毁第二个标题行。

对于任何多索引数据帧来说,它似乎非常通用且可重用。

df_styler = summary_df.style
# Use the df_styler to change display format, color, alignment, etc.
raw_html = df_styler.to_html()
soup = BeautifulSoup(raw_html,'html.parser')
head = soup.find('thead')
trs = head.find_all('tr')
ths0 = trs[0].find_all(lambda tag: (not tag.contents) or '\xa0' in tag.contents)
ths1 = trs[1].find_all(lambda tag: (tag.contents) or '\xa0' not in tag.contents)
for blank, filled in zip(ths0, ths1):
    blank.replace_with(filled)
trs[1].decompose()
final_html_str = soup.decode_contents()

Success - two header rows condensed into one

非常感谢 piRSquared 的美汤起点!

【讨论】:

    猜你喜欢
    • 2014-07-10
    • 2018-05-18
    • 2019-05-11
    • 1970-01-01
    • 2013-08-04
    • 2021-09-07
    • 1970-01-01
    相关资源
    最近更新 更多