Skip to content

Commit

Permalink
Support multiple column levels (#509)
Browse files Browse the repository at this point in the history
* Support multiple column levels

* Make repeated column titles span multiple columns

* Select table data with iloc rather than loc

* Include header breaks from  header levels

* remove unnecessary listcomp

* remove space from comment

* Go from itertools.accumlate to numpy.cumsum for python 2.7 compatibility

* remove numpy dependency

* Simplify running total
  • Loading branch information
shwinnn authored Jan 26, 2021
1 parent c852db9 commit a021585
Showing 1 changed file with 60 additions and 2 deletions.
62 changes: 60 additions & 2 deletions dash_bootstrap_components/_table.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from functools import reduce
from itertools import groupby
from operator import add

import dash_html_components as html


Expand Down Expand Up @@ -70,15 +74,69 @@ def _generate_table_from_df(
)
elif isinstance(header, dict):
df = df.rename(columns=header)

# Get the actual headers
n_levels = df.columns.nlevels
header_values = [
list(df.columns.get_level_values(level))
for level in range(n_levels)
]

# The sizes of consecutive header groups at each level
header_spans = [
[len(list(group)) for _, group in groupby(level_values)]
for level_values in header_values
]

# The positions of header changes for each level as an integer
header_breaks = [
[sum(level_spans[:i]) for i in range(1, len(level_spans) + 1)]
for level_spans in header_spans
]

# Include breaks from higher levels
header_breaks = [
sorted(set(reduce(add, header_breaks[:level])).union({0}))
for level in range(1, n_levels + 1)
]

# Go from header break positions back to cell spans
header_spans = [
reversed(
[
level_breaks[i] - level_breaks[i - 1]
for i in range(len(level_breaks) - 1, 0, -1)
]
)
for level_breaks in header_breaks
]

table = [
html.Thead(html.Tr(children=[html.Th(col) for col in df.columns]))
html.Thead(
[
html.Tr(
children=[
html.Th(
header_values[level][pos],
colSpan=span,
)
for pos, span in zip(
header_breaks[level], header_spans[level]
)
]
)
for level in range(n_levels)
]
)
]
else:
table = []
table.append(
html.Tbody(
[
html.Tr([html.Td(df.iloc[i][col]) for col in df.columns])
html.Tr(
[html.Td(df.iloc[i, j]) for j in range(len(df.columns))]
)
for i in range(len(df))
]
)
Expand Down

0 comments on commit a021585

Please sign in to comment.