Search code examples
pythonpandasonchangestreamlit

how to fix error "DataFrame object is not callable" in python and streamlit


I have a python code that display dataframe and allow the user to filter the dataframe by creating a new dataframe and allow him to update the requested record using the index number from the selectedbox.

For this reason i am using the new feature of streamlit session state where i want the system to preserve the filtered dataframe after the user change the the value of the selectbox by using the callback feature

The problem is that once the user select the value from the selectbox the system crash and display the below error:

TypeError: 'DataFrame' object is not callable
Traceback:
File "F:\AIenv\lib\site-packages\streamlit\script_runner.py", line 347, in _run_script
    self._session_state.call_callbacks()
File "F:\AIenv\lib\site-packages\streamlit\state\session_state.py", line 379, in call_callbacks
    self._new_widget_state.call_callback(wid)
File "F:\AIenv\lib\site-packages\streamlit\state\session_state.py", line 203, in call_callback
    callback(*args, **kwargs)

code:

import pandas as pd
import streamlit as st
        
def update_df(new_df):
    return pd.DataFrame(new_df)
        
def main():
    df=pd.read_csv(data)
    df_result_search = pd.DataFrame.from_records(df, columns = [column[0] for column in cursor.description])
    df_len = range(len(df_result_search.index))
    s = st.selectbox('Select index',key="select_box",options=df_len,on_change=update_df(df_result_search))
    expander_updates_fields = st.beta_expander('Update Records')
    with expander_updates_fields:
            for i, col in enumerate(df.columns):
                  if not s == 0:
                     val_update = st_input_update('Update {} from {} to:'.format(col, df[col].values[s]))
                     expander_updates_fields.markdown(val_update, unsafe_allow_html=True)
                  else:
                      st.write("DataFrame is empty")
    
    
if __name__=='__main__':
    main()
            

based on the answer of Joran Beasley

the system return the selected value but is not showing the dataframe

after the user select the value the page refresh this what is happening:

  1. dataframe disapper
  2. selectbox is saved the selected value
  3. the update expander return all the values of all records in each column.

So for this reason i used the callback()

what i want is to :

  1. dataframe still appear.
  2. selectbox is saved the selected value
  3. the update expander return values of the selected index number in each column.

How can I achieve these 3 tasks???

enter image description here


Solution

  • try doing

    on_change=lambda: update_df(df_result_search)

    before you basically had

    a_df = update_df(df_result_search)
    ... on_change=a_df
    

    on_change needs a function that it can call ... it cannot call the dataframe returned ... in the suggested solution we simply convert it into a lambda that will be called when the select choice is changed.

    (of coarse it probably passes some sort of "change_event" that you should probably use to select a column or something)

    ...on_change= lambda evt:do_something_with_event(evt)

    on further examination I think you do not quite understand how streamlit works

    this example should help you understand why you still have some issues

    import streamlit as st
    
    
    def main():
        s = st.selectbox('Select index',key="select_box",options=['a','b','c'],on_change=lambda *a:print("Old selection:",s))
        print("Current selection:",s) # now do something with it
    
    if __name__=='__main__':
        main()