Home > other >  Multilevel dataframe to dash table
Multilevel dataframe to dash table

Time:10-21

Having this dataframe:

enter image description here

What's the best way to display as a dashtable ? I've tried manipulating the columns manually but didn't work

bottom_col_row = df2.columns.get_level_values(1)  #------------
df2.columns = df2.columns.droplevel(1)             #------------
columns=[{'name': [x[0], x[1]], 'id': x[0]} for x in zip(df2.columns, bottom_col_row)]

CodePudding user response:

Alright, this was a little tricky, but here's one way to get it to work in Dash's dash_table open-source table library:

import dash
import numpy as np
import pandas as pd

from dash import dash_table

# Create a pd.MultiIndex from the combination of t & m:
t = ["1M", "3M", "6M", "1Y"]
m = ["IV", "RV", "Spread"]

arrays = np.array(sorted([[b, a] for a in m for b in t]))

df = pd.DataFrame(
    sorted(arrays, key=lambda x: (x[0][1], x[0][0])), columns=["Tenor", None]
)

index = pd.MultiIndex.from_frame(df)

# Create a mock df using random np floats, specifying the columns
# with the previously created pd.MultiIndex and the "index" here
# as the row labels
df2 = pd.DataFrame(
    np.around(np.random.randn(3, 12), decimals=2),
    index=["EURUSD", "GBPUSD", "USDJPY"],
    columns=index,
)

# Dash app
app = dash.Dash(__name__)

"""For getting the columns fed correctly to dash_table,
a two-row multi-header can be created by suppling 
the 'name' key of `DataTable.columns` with an array.

The trick then is to create unique IDs, which requires 
manipulation of the data into a list of dictionaries 
where each cell value's key is the artificially created
concatenated string (I just combined them; e.g., "1M_IV" 
is one of the unique keys, and so on).

Note: the use of '**' is a useful Python3  way to merge 
dicts during list/dict comprehensions. This is necessary
for including the true index 'Ccy Pair' as key,value 
pairs in addition to a dict comprehension through the data.
Thus I needed to also transpose the df..."""
 
app.layout = dash_table.DataTable(
    id="table",
    columns=[{"name": ["Tenor", "Ccy Pair"], "id": "Ccy Pair"}]
      [{"name": [x1, x2], "id": f"{x1}_{x2}"} for x1, x2 in df2.columns],
    data=[
        {
            **{"Ccy Pair": df2.index[n]},
            **{f"{x1}_{x2}": y for (x1, x2), y in data},
        }
        for (n, data) in [
            *enumerate([list(x.items()) for x in df2.T.to_dict().values()])
        ]
    ],
    merge_duplicate_headers=True,
    # Optional interactivity parameters*:
    editable=True,
    filter_action="native",
    sort_action="native",
    sort_mode="multi",
    column_selectable="single",
    row_selectable="multi",
    row_deletable=True,
    selected_columns=[],
    selected_rows=[],
    page_action="native",
    page_current= 0,
    page_size= 10,
)

if __name__ == "__main__":
    app.run_server(debug=True, dev_tools_hot_reload=True)

Which results in:

Dash app table when run

and with editing features added*:

Allowable sorting etc

Basically, this was the most helpful resource for me in figuring out how to manipulate the proper data structures: https://dash.plotly.com/datatable/style

Every cell has a [unique] column id which is f"{x1}_{x2}" where x1 ∈ ['1M', '3M', '6M', '1Y'] and x2 ∈ ['IV', 'RV', 'Spread']

  • Related