How to turn a dataframe with a list column into a dash Data Table, with the list contents as rows?

I have a dataframe with the columns

   App  | Week   | Top Users
 -------+--------+------------------------------
  App 1 | Week 1 |[1st user, 2nd user, 3rd user]

that shows the top 3 users of each app per week. The Top Users cells contain a list of the top 3 users.

Now i want to build a dash Data Table that gets updated when i select the App from a dropdown list.

I am trying to make the table look like this

 Week 1  | Week 2  | Week 3  | Week 4
---------+---------+------- -+----------
 1st user| 1st user| 1st user| 1st user
---------+---------+------- -+----------  
 2nd user| 2nd user| 2nd user| 2nd user
---------+---------+------- -+----------
 3rd user| 3rd user| 3rd user| 3rd user
    

    app = dash.Dash()

    top_users['Week'] = pd.DatetimeIndex(top_users['Week']).strftime("%d/%m/%Y")
    app_options = []
    for apps in top_users['App'].unique():
        app_options.append({'label':str(apps), 'value':apps})

    weeks = []
    for week in top_users['Week'].unique():
        weeks.append(week)


    app.layout = html.Div(children=[
                        dash_table.DataTable(
                        id='top-users',
                        columns=[{"name": i, "id": i} for i in weeks],
                        fixed_rows={'headers': True}
                        ) ,
                        dcc.Dropdown(id='app-picker', options=app_options),                               
                        ])

    @app.callback(
    Output('top-users', 'data'),
    Input('app-picker', 'value'))
    def update_table(selected_app):    
        data = top_users.loc[top_users['App']==selected_app]
        return data.to_dict('records')
    
    if __name__ == '__main__':
        app.run_server(host="127.0.0.1", port=8060)

The code above doesn’t show anything at all

Hi,

Welcome to the community! :slight_smile:

The problem is the format of data. DataTable expects the data to have keys matching the ids provided in `columns, or in other words, the dataframe should have columns named “Week 1”, “Week 2” and so on… In your code it currently has “App”, “Week” and “Top Users” instead, and this is the reason why there is nothing in the table.

Now you have to redefine the pandas dataframe to match the format you want, where each column is a different week and each row contains the n-th top user of each week. Concretely, you have (for a given selected app, after your first filter):

df = pd.DataFrame(
    data={
        "App": ["A", "A"],
        "Week": ["W1", "W2"],
        "Top Users": [
            ["a", "b", "c"],
            ["d", "e", "f"]
        ]
    }
)

A quick way to transform it is to transpose the dataframe and explode all columns. The Week values will be the first row, which you can assign as column name and drop. So:

df = df[["Week", "Top Users"]].transpose().explode([i for i in range(len(df["Week"].unique()))])
df.rename(columns=df.iloc[0], inplace=True)
df.drop(df.index[0], inplace = True)
df.reset_index(drop=True, inplace=True)

df.to_dict("records") will look like this:

[{'W1': 'a', 'W2': 'd'}, {'W1': 'b', 'W2': 'e'}, {'W1': 'c', 'W2': 'f'}]