# Dash table update values for column/ row based on callback/user input from another column

**URL:** <https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872>\
**Category:** Dash Python\
**Created:** [September 14, 2020, 1:46pm UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872 "2020-09-14T13:46:06Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![jing0703](https://avatars.discourse-cdn.com/v4/letter/j/839c29/32.png) [@jing0703](https://community.plotly.com/u/jing0703)\
**Post date:** [September 14, 2020, 1:46pm UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872/1 "2020-09-14T13:46:06Z")

</div>

Hello, I am using data table to build interactive table which is editable for one column. Could I update value for other columns in the same table when user enter input value? As long as table data can’t be both input and output in the same callback. I can’t think about a strategy to achieve this. Could anyone help with it? Many thanks!

---

<div class="post-metadata">

**Author:** ![AnnMarieW](https://avatars.discourse-cdn.com/v4/letter/a/ec9cab/32.png) [@AnnMarieW](https://community.plotly.com/u/AnnMarieW)\
**Post date:** [September 14, 2020, 2:48pm UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872/2 "2020-09-14T14:48:10Z")

</div>

Hi @jing0703

Check out this link: [https://dash.plotly.com/datatable/editable](https://dash.plotly.com/datatable/editable)

See the example called " Updating Columns of the Same Table"

It sounds like what you are looking for

---

<div class="post-metadata">

**Author:** ![jing0703](https://avatars.discourse-cdn.com/v4/letter/j/839c29/32.png) [@jing0703](https://community.plotly.com/u/jing0703)\
**Post date:** [September 14, 2020, 3:08pm UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872/3 "2020-09-14T15:08:29Z")

</div>

> [@AnnMarieW](#):
>
> Updating Columns of the Same Table

Hi @AnnMarieW, that’s it! I should check the document carefully. Thank you so much!

---

<div class="post-metadata">

**Author:** ![keval](https://avatars.discourse-cdn.com/v4/letter/k/ec9cab/32.png) [@keval](https://community.plotly.com/u/keval)\
**Post date:** [October 8, 2020, 1:58pm UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872/4 "2020-10-08T13:58:24Z")

</div>

@AnnMarieW @jing0703

I am working on the same update, except, my data-table is updated on callback and then when the user makes a change to editable column, I’d like to update another column in same data-table. My problem is I can’t have a second callback for data-table, so I need to do it in the same one. Here’s my code:

```auto

# Update DataTable
@app.callback(Output("deal-table", "data"),
              [

                  Input("income", "value"),
                  Input("expenses", "value"),
                  Input("lease-button", "n_clicks"),
                  Input("deal-table", "data_timestamp")

              ],
              [
                  State("deal-table", "data"),
                  State("comps-store", "data")
              ]
             )
def cashflow_table(income, expenses, n_clicks, timestamp, rows, comps_store):

    if n_clicks:

        # Construct Pandas DataFrame
        df = pd.DataFrame({
                           "Year": year_list,
                           "Periods": np.nan,
                           "Income": np.nan,
                           "Expenses": np.nan,
                           "Cash Flow": np.nan
                         })

        # Update a column based on user input
        if rows:
           for row in rows:
               try:
                  row['Cash Flow'] = row['Income'] - row['Expenses']
               except:
                  row['Cash Flow'] = 0

        df_table = df.to_dict("rows")

        return (df_table)

    else:

       return (no_update)

```

This doesn’t work.

---

<div class="post-metadata">

**Author:** ![AnnMarieW](https://avatars.discourse-cdn.com/v4/letter/a/ec9cab/32.png) [@AnnMarieW](https://community.plotly.com/u/AnnMarieW)\
**Post date:** [October 8, 2020, 4:45pm UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872/5 "2020-10-08T16:45:12Z")

</div>

Hi @keval

I think I see what’s going on.

A bit of background for others who might be new to this: The content of a dash DataTable, the `data` parameter, is a list of dictionaries. In most of the examples in the Dash tutorial, the data for the app starts as a dataframe, and before it’s used in the DataTable, it’s converted to the correct format using the Pandas function `data=df.to_dict('records')`

In the Editable DataTable example, the `data` is used as an input argument in the callback function - in this example it’s called `rows`

```auto
@app.callback(
    Output('computed-table', 'data'),
    [Input('computed-table', 'data_timestamp')],
    [State('computed-table', 'data')])
def update_columns(timestamp, rows):
    for row in rows:
        try:
            row['output-data'] = float(row['input-data']) ** 2
        except:
            row['output-data'] = 'NA'
    return rows

```

Note that the data stays in the original format - a list of dictionaries. So there is no need to convert it, you can just use `return rows`

If you prefer to do the calculations using Pandas, you can start by converting `rows` to df like this:

```auto
def update_columns(timestamp, rows):
    df=pd.DataFrame(rows)

    # do calculations using pandas

    return df.to_dict('records')

```

(In your example df.to\_dict(“rows”) the “rows” is not a valid parameter [https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to\_dict.html](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_dict.html))

If this is still unclear, if you provide a minimal working example (including sample data) I might be able to be more helpful.

---

<div class="post-metadata">

**Author:** ![keval](https://avatars.discourse-cdn.com/v4/letter/k/ec9cab/32.png) [@keval](https://community.plotly.com/u/keval)\
**Post date:** [October 8, 2020, 6:37pm UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872/6 "2020-10-08T18:37:49Z")

</div>

Hi @AnnMarieW -

Thanks for the background and pointing out the distinction between `rows`.

My initial DataFrame is generated and rendered from the callback, unlike the example here:[https://dash.plotly.com/datatable/editable](https://dash.plotly.com/datatable/editable). I do the calculations in the callback function as well.  
When the user updates an editable column, I’d like to update the values in another column in same data-table.

Here’s a minimal reproducible example:

```auto
import dash
from dash.dependencies import Input, Output, State
import dash_table
import dash_html_components as html

app = dash.Dash( __name__ )

app.layout = html.Div([

    dbc.Button("Run", id="dt-button", size="lg"),

    dash_table.DataTable(
        id='table1',
        columns=[
            {'name': 'Year', 'id': 'year'},
            {'name': 'Income', 'id': 'income'},
            {'name': 'Expenses', 'id': 'expense'},
            {'name': 'Cash flow', 'id': 'cash flow'}
        ],
      
        editable=True,
    ),
])

# Callback

@app.callback(Output("table1", "data"),
                     [

                        Input("dt-button", "n_clicks"),
                        Input("table1", "data_timestamp")
                       
                    ],
                    [
                       State("table1", "data"),
                   ]
                  )
def table(n_clicks, timestamp, rows):

         if n_clicks:
            # Construct Pandas DataFrame 
             df = pd.DataFrame({
                                           "Year": ['2018','2019','2020'],
                                           "Income": ['200','300','400'],
                                           "Expense": np.nan, # Editable column, user inputs expenses
                                           "Cash Flow": np.nan #Income - expense
                                        })

            # Update columns
            for row in rows:
                 try:
                      row['cash flow'] = (row['income'] - row['expense']) # Expense is entered by the user
                except:
                      row['cash flow'] = row['income']

            df_table = df.to_dict("records")

            return (df_table)

         else:

           return (no_update)

```

---

<div class="post-metadata">

**Author:** ![AnnMarieW](https://avatars.discourse-cdn.com/v4/letter/a/ec9cab/32.png) [@AnnMarieW](https://community.plotly.com/u/AnnMarieW)\
**Post date:** [October 8, 2020, 7:53pm UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872/7 "2020-10-08T19:53:30Z")

</div>

Hi @keval

Since you want to generate the initial dataframe in the callback, you need to know which input triggered the callback - either the start button, or the the user entering data in the table. You can do that by using callback\_context. More info on that here: [https://dash.plotly.com/advanced-callbacks](https://dash.plotly.com/advanced-callbacks)

Here is something to get you started - based on the code you provided:

```auto
import dash
from dash.dependencies import Input, Output, State
import dash_table
import dash_html_components as html
import pandas as pd

app = dash.Dash( __name__ )

app.layout = html.Div(
    [
        html.Button("Run", id="dt-button"),
        dash_table.DataTable(
            id="table1",
            columns=[
                {"name": "Year", "id": "Year"},
                {"name": "Income", "id": "Income", "type": "numeric"},
                {"name": "Expenses", "id": "Expense", "type": "numeric"},
                {"name": "Cash flow", "id": "Cash Flow", "type": "numeric"},
            ],
            editable=True,
        ),
    ]
)

@app.callback(
    Output("table1", "data"),
    [Input("dt-button", "n_clicks"), Input("table1", "data_timestamp")],
    [State("table1", "data"),],
)
def table(n_clicks, timestamp, rows):

    ctx = dash.callback_context
    input_id = ctx.triggered[0]["prop_id"].split(".")[0]

    if input_id == "dt-button":       
        df = pd.DataFrame(
            {
                "Year": ["2018", "2019", "2020"],
                "Income": [200, 300, 400],
                "Expense": [0, 0, 0], # Editable column, user inputs expenses
                "Cash Flow": [0, 0, 0], # Income - expense
            }
        )
        return df.to_dict("records")

    if rows:
        for row in rows:
            try:
                row["Cash Flow"] = (row["Income"] - row["Expense"])
            except:
                row["Cash Flow"] = row["Income"]
        return rows
    else:
        return dash.no_update

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

```

---

<div class="post-metadata">

**Author:** ![keval](https://avatars.discourse-cdn.com/v4/letter/k/ec9cab/32.png) [@keval](https://community.plotly.com/u/keval)\
**Post date:** [October 9, 2020, 7:44am UTC](https://community.plotly.com/t/dash-table-update-values-for-column-row-based-on-callback-user-input-from-another-column/44872/9 "2020-10-09T07:44:31Z")

</div>

@AnnMarieW

Converting to pandas dataframe, like you suggested worked for me. Here’s the code snippet to update column value based on edits from another column in same data-table:

```auto
    # Check state
    if rows and timestamp:
        # Convert to Pandas DataFrame
        df = pd.DataFrame(rows)

        for index, row in df.iterrows():

            if row['Expense'] is not None:

                df.at[index, 'Cash Flow'] = int(row['Income']) - int(row['Expense'])

        return df.to_dict('records')

```

Thanks for your help.
