Home > Blockchain >  How do I arrange and code data for a Dash plotly editable datatable?
How do I arrange and code data for a Dash plotly editable datatable?

Time:12-06

I have spent this week trying to figure out how to design an editable datatable via Flask without much success. I found the plugin bootstable, and I had my table ready to go, with the data populating the cells perfectly. But I could not pip install jquery (required) and its dependencies. This appears to be a common problem, evidenced by the posts I saw online.

So I circled back to the editable Dash/plotly datatables.

My problem here is that I cannot figure out how to populate the cells with the data I need to use. I pasted the code from one the Dash editable templates below as an example, as well as my best attempt to make it work. Changing the columns is easy. And the code works fine with the dummy data, but I cannot figure out how to make my data (currently in JSON form ) compatible with this template. I have poured over the Dash/Plotly website and I don't see much direction on this topic.

How would arrange my data so that it can be used by data=[ ] in the code below?

My data is a list of Python dictionaries currently in JSON form, and sent as a simple list via Flask to index.html. I know it transfers because it works in other unsuccessful attempts. I just can't install the dependencies, as noted above. I could easily transform it into a CSV file if necessary. Does anyone know how to resolve this issue?

Any help at this point would be greatly appreciated.

Here is the template online, found at this address.

import dash
from dash.dependencies import Input, Output
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd

app = dash.Dash(__name__)

params = [
    'Weight', 'Torque', 'Width', 'Height',
    'Efficiency', 'Power', 'Displacement'
]

app.layout = html.Div([
    dash_table.DataTable(
        id='table-editing-simple',
        columns=(
            [{'id': 'Model', 'name': 'Model'}]  
            [{'id': p, 'name': p} for p in params]
        ),
        data=[
            dict(Model=i, **{param: 0 for param in params})
            for i in range(1, 5)
        ],
        editable=True
    ),
    dcc.Graph(id='table-editing-simple-output')
])


@app.callback(
    Output('table-editing-simple-output', 'figure'),
    Input('table-editing-simple', 'data'),
    Input('table-editing-simple', 'columns'))
def display_output(rows, columns):
    df = pd.DataFrame(rows, columns=[c['name'] for c in columns])
    return {
        'data': [{
            'type': 'parcoords',
            'dimensions': [{
                'label': col['name'],
                'values': df[col['id']]
            } for col in columns]
        }]
    }


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

Here is my attempt to make it work, though I receive an "Error loading layout" message, where user_edits is the list of dictionaries and each_dict is each dictionary in the list.

Thank you for any sincere feedback.

app = dash.Dash(__name__)

with open("./json/flask_dict.json", "r") as flask_dicts:
   user_edits = json.load(flask_dicts)

app.layout = html.Div([
    dash_table.DataTable(
        id='table-editing-simple',
        columns=(
            [{'id': 'Index', 'name': 'Index'}]  
            [{'id': 'Amounts', 'name': 'Amounts'}]  
            [{'id': 'Modifiers', 'name': 'Modifiers'}]  
            [{'id': 'Units', 'name': 'Units'}]  
            [{'id': 'Ings', 'name': 'Ings'}]            
        ),
        data=[{v for k,v in each_dict.items()} for each_dict in user_edits],
        editable=True
    ),
    dcc.Graph(id='table-editing-simple-output')
])

In case it helps, here is the list of dictionaries:

[
    {'index': 0, 'amount': '.5', 'mod': 'None', 'units': 'teaspoon', 'ing': 'dried oregano'},
    {'index': 1, 'amount': '0.25', 'mod': 'None', 'units': 'tsp', 'ing': 'red chilli flakes'},
    {'index': 2, 'amount': '0.25', 'mod': 'None', 'units': 'tsp', 'ing': 'ground cloves'},
    {'index': 3, 'amount': '1', 'mod': 'None', 'units': 'tbsp', 'ing': 'sunflower oil'},
    {'index': 4, 'amount': '1', 'mod': 'None', 'units': 'tsp', 'ing': 'mustard seeds'},
    {'index': 5, 'amount': '1', 'mod': 'divided', 'units': 'tsp', 'ing': 'salt'},
    {'index': 6, 'amount': '1.33', 'mod': 'None', 'units': 'tsp', 'ing': 'cumin'},
    {'index': 7, 'amount': '1.5', 'mod': 'None', 'units': 'teaspoon', 'ing': 'dried thyme'},
    {'index': 8, 'amount': '10', 'mod': 'None', 'units': 'teaspoon', 'ing': 'cardamom pods'},
    {'index': 9, 'amount': '3', 'mod': 'None', 'units': 'cm', 'ing': 'ginger'},
    {'index': 10, 'amount': '3', 'mod': 'medium', 'units': 'cm', 'ing': 'shallots'},
    {'index': 11, 'amount': '300', 'mod': 'None', 'units': 'grams', 'ing': 'red lentils'},
    {'index': 12, 'amount': '4', 'mod': 'minced', 'units': 'grams', 'ing': 'cloves of garlic'},
    {'index': 13, 'amount': '400', 'mod': 'None', 'units': 'grams', 'ing': 'diced tomatoes'},
    {'index': 14, 'amount': '80', 'mod': 'None', 'units': 'grams', 'ing': 'baby spinach'},
    {'index': 15, 'amount': '1', 'mod': 'None', 'units': 'handful', 'ing': 'cilantro'},
    {'index': 16, 'amount': '1', 'mod': 'Half', 'units': 'handful', 'ing': 'lemon'}
]

CodePudding user response:

The data parameter of DataTable is expecting the format to be a list of dictionaries, that's true. But the dictionary format is expected to be like: {'columnName':'value'}. Your list comprehension is removing the key (column name) and only including the value, and is returned as a set. What you've made is a list of sets.

Try setting data = user_edits. It appears the format is already correct and no comprehensions are required.

Edit: On second glance, you will need to update your columns object to match the same spelling and case as the keys in your data object. E.g "Amounts" vs "amount" -- these need to match.

CodePudding user response:

With some assistance from the Dash/Plotly community, I was finally able to figure this one out.

My data below was already structured in the right way, so I did that much right. I only needed to set the data equal to my list of dictionaries.

My mistake was thinking I needed to iterate through it.

Here is the input and code if you wish to try it:

1) List of dictionaries that needed to be placed inside an editable table:

recipe_ents_list = [{'Index': 0, 'Amounts': '.5', 'Modifiers': 'None', 'Units': 'teaspoon', 'Ings': 'dried oregano'},
{'Index': 1, 'Amounts': '0.25','Modifiers': 'None', 'Units': 'tsp', 'Ings': 'red chilli flakes'},
{'Index': 2, 'Amounts': '0.25', 'Modifiers': 'None', 'Units': 'tsp', 'Ings': 'ground cloves'},
{'Index': 3, 'Amounts': '1', 'Modifiers': 'None', 'Units': 'tbsp', 'Ings': 'sunflower oil'},
{'Index': 4, 'Amounts': '1', 'Modifiers': 'None', 'Units': 'tsp', 'Ings': 'mustard seeds'},
{'Index': 5, 'Amounts': '1', 'Modifiers': 'divided', 'Units': 'tsp', 'Ings': 'salt'},
{'Index': 6, 'Amounts': '1.33', 'Modifiers': 'None', 'Units': 'tsp', 'Ings': 'cumin'},
{'Index': 7, 'Amounts': '1.5', 'Modifiers': 'None', 'Units': 'teaspoon', 'Ings': 'dried thyme'},
{'Index': 8, 'Amounts': '10', 'Modifiers': 'None', 'Units': 'teaspoon', 'Ings': 'cardamom pods'},
{'Index': 9, 'Amounts': '3', 'Modifiers': 'None', 'Units': 'cm', 'Ings': 'ginger'},
{'Index': 10, 'Amounts': '3', 'Modifiers': 'medium', 'Units': 'cm', 'Ings': 'shallots'},
{'Index': 11, 'Amounts': '300', 'Modifiers': 'None', 'Units': 'grams', 'Ings': 'red lentils'},
{'Index': 12, 'Amounts': '4', 'Modifiers': 'minced', 'Units': 'grams', 'Ings': 'cloves of garlic'},
{'Index': 13, 'Amounts':'400', 'Modifiers': 'None', 'Units': 'grams', 'Ings': 'diced tomatoes'},
{'Index': 14, 'Amounts': '80', 'Modifiers': 'None', 'Units': 'grams', 'Ings': 'baby spinach'},
{'Index': 15, 'Amounts': '1', 'Modifiers': 'None', 'Units': 'handful','Ings': 'cilantro'},
{'Index': 16, 'Amounts': '1', 'Modifiers': 'Half', 'Units': 'handful', 'Ings': 'lemon'}]

2) Here is the final, working code. You can replicate the plot with the dictionaries above and the code below. It desperately need formatting, but it is accurate and editable.

from dash import Dash, dcc, html, dash_table

app = Dash(__name__)

app.layout = html.Div([
    dash_table.DataTable(
        id='table-editing-simple',
        columns=[{'id': i, 'name':i} for i in ['Index', 'Amounts', 'Modifiers', 'Units', 'Ings']],
        data=recipe_ents_list,
        editable=True
    ),
    dcc.Graph(id='table-editing-simple-output')
])

if __name__ == "__main__":
    app.run_server(debug=True)
  • Related