I’m working on generating an HTML table dynamically in Python based on a pandas DataFrame. The table includes both for headers and for rows of data. However, I’m running into an issue where my rows () are not properly contained within a single tag.
Here is the function I currently have:
def Analyse(df_multiselect):
# Define the table structure with thead and tbody in one place
table_html = """
<table id="data-table" class="table display nowrap" width="auto">
<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>
<tbody>
"""
# Dynamically select subjects and columns
subjects = df_multiselect.columns[11:26] # Modify to match your actual column indices
columns = df_multiselect.iloc[:, 11:26]
# Calculate the statistics
counts = columns.count()
means = round(columns.mean(), 2)
stdvs = round(columns.std(), 2)
maxs = columns.max()
mins = columns.min()
ranges = round(maxs - mins, 2)
variances = round(columns.var(), 2)
medians = round(columns.median(), 2)
# Loop through each subject to build the table rows
for i, subject in enumerate(subjects):
row = f"""
<tr>
<td>{subject}</td>
<td>{counts.iloc[i]}</td>
<td>{means.iloc[i]:.2f}</td>
<td>{stdvs.iloc[i]:.2f}</td>
<td>{variances.iloc[i]:.2f}</td>
<td>{mins.iloc[i]}</td>
<td>{medians.iloc[i]}</td>
<td>{maxs.iloc[i]}</td>
<td>{ranges.iloc[i]}</td>
</tr>
"""
table_html += row # Add the current row to the table HTML
# Close the tbody tag and the table
table_html += "</tbody></table>"
return table_html
# Generate the table HTML by calling Analyse
table_html = Analyse(df_multiselect)
# Generate the full HTML page to display
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>
"""
# Display the HTML content in Streamlit using st.markdown
st.markdown(full_html, unsafe_allow_html=True)
Problem:
This function seems to generate only one inside the tag, while the other rows are placed outside the in the resulting HTML. I need all rows to be properly encapsulated inside a single tag.
What I’ve Tried:
I checked the loop logic and ensured all rows are being added inside the loop.
Verified the final table_html structure by printing it, and the issue persists.
Desired Output:
A valid HTML table where all rows are correctly contained within one tag.
Example Expected Table:
<table>
<thead>
<tr>
<th>Subject</th>
<th>Count</th>
<th>Mean</th>
<th>Std Dev</th>
<th>Variance</th>
<th>Max</th>
<th>Median</th>
<th>Min</th>
<th>Range</th>
</tr>
</thead>
<tbody>
<tr>
<td>Math</td>
<td>30</td>
<td>14.56</td>
<td>2.34</td>
<td>5.48</td>
<td>20</td>
<td>15</td>
<td>10</td>
<td>10</td>
</tr>
<tr>
<td>Science</td>
<td>28</td>
<td>13.42</td>
<td>2.12</td>
<td>4.98</td>
<td>19</td>
<td>14</td>
<td>11</td>
<td>8</td>
</tr>
<!-- Additional rows -->
</tbody>
</table>
2
Answers
problem resolved: The suggestion to remove trailing newlines in my row construction is a good one so i have Updated my loop to avoid extra whitespace.
Why going through all that complexity when you can simply use pandas.DataFrame.to_html?! It will write the html from the df for you in 1 line.