You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中基于Pandas DataFrame正确动态生成包含<thead>与<tbody>的完整HTML表格?

如何在Python中基于Pandas DataFrame正确动态生成包含与的完整HTML表格?

嘿,我看了你的问题和代码,理论上你的拼接逻辑方向是对的,但可能是字符串拼接时的格式细节或者索引匹配问题,导致<tr>没有被正确包裹在<tbody>标签里。给你两个实用的调整方案,帮你解决这个问题:

方案一:优化字符串拼接逻辑,避免索引匹配错误

原来的代码里用enumerate(subjects)再通过iloc[i]取统计值,万一subjects和统计序列的索引顺序不匹配,就可能导致行内容异常;另外用列表收集行内容再合并,比逐段拼接字符串更清晰,不容易出现格式漏洞。

修改后的函数如下:

import pandas as pd
import streamlit as st

def Analyse(df_multiselect):
    # 定义固定的表头部分
    thead_html = """
    <thead>
        <tr>
            <th colspan="1">المواد</th>
            <th colspan="1">الحاضرون</th>
            <th colspan="1">المتوسط الحسابي</th>
            <th colspan="1">الانحراف المعياري</th>
            <th colspan="1">التباين</th>
            <th colspan="1">أعلى نقطة</th>
            <th colspan="1">الوسيط</th>
            <th colspan="1">أدنى نقطة</th>
            <th colspan="1">المدى</th>
        </tr>
    </thead>
    """
    
    # 动态选择科目列
    subjects = df_multiselect.columns[11:26]
    columns = df_multiselect.iloc[:, 11:26]

    # 把统计量整理成字典,直接用科目名索引更可靠
    stats = {
        "count": columns.count(),
        "mean": round(columns.mean(), 2),
        "std": round(columns.std(), 2),
        "var": round(columns.var(), 2),
        "max": columns.max(),
        "min": columns.min(),
        "range": round(columns.max() - columns.min(), 2),
        "median": round(columns.median(), 2)
    }

    # 用列表收集所有tbody行,避免逐段拼接的格式问题
    tbody_rows = []
    for subject in subjects:
        row = f"""
        <tr>
            <td>{subject}</td>
            <td>{stats['count'][subject]}</td>
            <td>{stats['mean'][subject]:.2f}</td>
            <td>{stats['std'][subject]:.2f}</td>
            <td>{stats['var'][subject]:.2f}</td>
            <td>{stats['min'][subject]}</td>
            <td>{stats['median'][subject]}</td>
            <td>{stats['max'][subject]}</td>
            <td>{stats['range'][subject]:.2f}</td>
        </tr>
        """
        tbody_rows.append(row)
    
    # 组合tbody部分
    tbody_html = f"<tbody>{''.join(tbody_rows)}</tbody>"

    # 拼接完整表格
    table_html = f"""
    <table id="data-table" class="table display nowrap" width="auto">
        {thead_html}
        {tbody_html}
    </table>
    """

    return table_html


# 调用函数生成表格
table_html = Analyse(df_multiselect)

# 生成完整HTML页面
full_html = f"""
    <section>
        <div class="container">
            <div class="row g-5 align-items-center">
                <a id="titleElement" class="btn btn-primary-soft">تحليل النتائج
                </a>
                <div class="about-image-gallery">
                    <div class="scroll-container">    
                        {table_html}
                    </div> 
                </div>
            </div>
        </div>
    </section>
"""

# 在Streamlit中渲染
st.markdown(full_html, unsafe_allow_html=True)

方案二:利用Pandas内置的to_html方法,减少手动拼接工作量

Pandas的DataFrame.to_html方法可以自动生成带<thead>和<tbody>的标准HTML表格,我们只需要先把统计量整理成新的DataFrame,再生成表格即可,这样几乎不会出现手动拼接的格式错误:

import pandas as pd
import streamlit as st

def Analyse(df_multiselect):
    # 动态选择目标列
    columns = df_multiselect.iloc[:, 11:26]
    
    # 把所有统计量整理成一个新的DataFrame
    stats_df = pd.DataFrame({
        "المواد": columns.columns,
        "الحاضرون": columns.count(),
        "المتوسط الحسابي": round(columns.mean(), 2),
        "الانحراف المعياري": round(columns.std(), 2),
        "التباين": round(columns.var(), 2),
        "أعلى نقطة": columns.max(),
        "الوسيط": round(columns.median(), 2),
        "أدنى نقطة": columns.min(),
        "المدى": round(columns.max() - columns.min(), 2)
    })
    
    # 直接生成标准HTML表格,设置参数指定样式和ID
    table_html = stats_df.to_html(
        index=False,  # 去掉默认的索引列
        classes="table display nowrap",
        table_id="data-table",
        col_space="auto"
    )
    
    # 如果需要更自定义的表头(比如调整colspan),可以替换默认的thead部分
    custom_thead = """
    <thead>
        <tr>
            <th colspan="1">المواد</th>
            <th colspan="1">الحاضرون</th>
            <th colspan="1">المتوسط الحسابي</th>
            <th colspan="1">الانحراف المعياري</th>
            <th colspan="1">التباين</th>
            <th colspan="1">أعلى نقطة</th>
            <th colspan="1">الوسيط</th>
            <th colspan="1">أدنى نقطة</th>
            <th colspan="1">المدى</th>
        </tr>
    </thead>
    """
    # 替换原有的thead
    start_idx = table_html.find("<thead>")
    end_idx = table_html.find("</thead>") + 8
    table_html = table_html.replace(table_html[start_idx:end_idx], custom_thead)
    
    return table_html


# 后续调用和渲染代码和方案一一致
table_html = Analyse(df_multiselect)
full_html = f"""
    <section>
        <div class="container">
            <div class="row g-5 align-items-center">
                <a id="titleElement" class="btn btn-primary-soft">تحليل النتائج
                </a>
                <div class="about-image-gallery">
                    <div class="scroll-container">    
                        {table_html}
                    </div> 
                </div>
            </div>
        </div>
    </section>
"""
st.markdown(full_html, unsafe_allow_html=True)

额外检查建议

你可以先打印table_html的完整内容,确认<tbody>标签是否正确包裹了所有<tr>行。如果打印出来的HTML是标准正确的,但Streamlit显示有异常,可能是容器的CSS样式导致视觉上的错觉,你可以给scroll-container添加合适的溢出样式,比如:

.scroll-container {
    overflow-x: auto;
    white-space: nowrap;
}

备注:内容来源于stack exchange,提问作者Haddadi Abdraouf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 10:43:03