Dash_table with Multi-level header

Hello community,
Have a list

data =[
   {'A': {'ABC': '1234', 'QWE': '2342'}},
   {'B': {'ABC': '234', 'QWE': '3424', 'RTY': 'qwert'}},
   {'A': {'ABC': '2342', 'QWE': '23424'}},
   {'B': {'ABC': '2342', 'QWE': '23442', 'RTY': 'tree'}},
   {'A': {'ABC': '2344', 'QWE': '3424'}},
   {'B': {'ABC': '2344', 'QWE': '2344', 'RTY': 'awed'}}
]

Could you tell me how you can display a table in a universal way in Dash Table
in following format

  A       |      B
ABC | QWE | ABC | QWE | RTY

Thank you

Hi @dilfin07

https://dash.plotly.com/datatable/style

See the title Multi-Headers

Thank you for replay,
Already watched this post, unfortunately, it does not come out to get the desired result

@dilfin07

Do you mean that merge_duplicate_headers=True, doesen’t work in your example?? :thinking:

Unfortunately, yes, I need a universal way to display such attachments in the table, tried to convert the given list to a dateframe and load into a table, but I get a load error layout

@dilfin07

How do you convert the given list to a dataframe ?

from itertools import groupby

data2 = [[(k, k2), v2] for d in data for k,v in d.items() for k2,v2 in v.items()]

res = pd.DataFrame({k: [x[1] for x in g] 
                    for k,g in groupby(sorted(data2), key=lambda x: x[0])})

this way I got a dataframe from the given list

Hi @dilfin07

Using the example of the link and changing your code to generate the DataFrame I acomplished what you need, I shure there must exist a better solution, but it works:

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
import dash_table
from itertools import groupby

data =[
   {'A': {'ABC': '1234', 'QWE': '2342'}},
   {'B': {'ABC': '234', 'QWE': '3424', 'RTY': 'qwert'}},
   {'A': {'ABC': '2342', 'QWE': '23424'}},
   {'B': {'ABC': '2342', 'QWE': '23442', 'RTY': 'tree'}},
   {'A': {'ABC': '2344', 'QWE': '3424'}},
   {'B': {'ABC': '2344', 'QWE': '2344', 'RTY': 'awed'}}
]

data2 = [[k2+k, v2] for d in data for k,v in d.items() for k2,v2 in v.items()]

res = pd.DataFrame({k: [x[1] for x in g] 
                    for k,g in groupby(sorted(data2), key=lambda x: x[0])})

app = dash.Dash(__name__)

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),
    dash_table.DataTable(
        columns=[
                {"name": ["A", "ABC"], "id": "ABCA"},
                {"name": ["A", "QWE"], "id": "QWEA"},
                {"name": ["B", "ABC"], "id": "ABCB"},
                {"name": ["B", "QWE"], "id": "QWEB"},
                {"name": ["B", "RTY"], "id": "RTYB"},
            ],
            data =res.to_dict('records'),
        merge_duplicate_headers=True,
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)

As I’m not a code expert in using things like { k, v, i, etc } for … I’ll let you the part of generating a variable that bild the columns property as shown in the code taking the information from your data.

This is the table generated with this code:

Thanks, this is a working solution, but not quite suitable for my task,
since the column and count of attachment are constantly changing, in this regard, and I’m looking for a solution to dynamically fill the table on the page

That means you do not know how to bild the columns dynamicaly?
I think it could be not too difficult.

In this case, yes, could you help me with some examples for this case, with the condition of attachments?

@dilfin07

Well as I said: I not familiar working with this stuff.

But esentially what I did is trying to transform the dataframe to adjust to the example.

  1. transform the two columns dataframe with only one column dataframe where the colums name are the concatenation of the two columns (in this case “second column+first column”)

  2. bild a variable columns that has the layout that the example requires: columns={“name”:[“first column”, “second column”], “id”: “second column+first column”},

If you can generate that dynamicaly, you can solve your problem.

This example do what is expected, but as an accountant I do not know to bild in a way that is dynamicaly consistent. But I think could not be so difficult.

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
import dash_table
from itertools import groupby

data =[
   {'A': {'ABC': '1234', 'QWE': '2342'}},
   {'B': {'ABC': '234', 'QWE': '3424', 'RTY': 'qwert'}},
   {'A': {'ABC': '2342', 'QWE': '23424'}},
   {'B': {'ABC': '2342', 'QWE': '23442', 'RTY': 'tree'}},
   {'A': {'ABC': '2344', 'QWE': '3424'}},
   {'B': {'ABC': '2344', 'QWE': '2344', 'RTY': 'awed'}}
]

data2 = [[k2+k, v2] for d in data for k,v in d.items() for k2,v2 in v.items()]

res = pd.DataFrame({k: [x[1] for x in g] 
                    for k,g in groupby(sorted(data2), key=lambda x: x[0])})

newcol = [{"name": [k,k2],"id": k2+k,} for d in data for k,v in d.items() for k2,v2 in v.items()]

# function to get unique values 
def unique(list1): 
  
    # intilize a null list 
    unique_list = [] 
      
    # traverse for all elements 
    for x in list1: 
        # check if exists in unique_list or not 
        if x not in unique_list: 
            unique_list.append(x)
    
    return unique_list

columns = unique( newcol)

app = dash.Dash(__name__)

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),
    dash_table.DataTable(
        columns=columns,
            data =res.to_dict('records'),
        merge_duplicate_headers=True,
    )
])

if __name__ == '__main__':
    app.run_server(debug=True)

Hello,
Many thanks, you helped a lot