pythonstreamlit

Error when processing Data File with a Streamlit App


I am trying to deploy an app which processes a .csv data file inputted by the user and performs some dimensional analysis with it and produces plots. The Github repo can be found at 1.

The file which I run is called ‘‘streamlitstuff.py’’ and the other file on the repo which has errors is the data reader file ‘‘data_reader.py’’.

The website is created as expected but when I try to input a .csv data file in the required format I receive the below error messages, can anyone advise? I have also attached an image for what is seen on the website with the same message.

Although there is a message about the index being out of range, I have used this data file before with a previous version of the code about two years ago so there has been some bug in the code which developed since then or something which no longer works and needs to be changed. From looking at the data table on the left-hand side where there are alternating rows of ''None'', it looks like something is wrong with how the indexing of the rows is done.

File “C:\Users\holli\miniconda3\Lib\site-packages\streamlit\runtime\scriptrunner\script_runner.py”,
line 600, in _run_script
exec(code, module.dict)
File “C:\Users\holli\streamlitstuff.py”, line 61, in
data = Data(ds, pandas=True)
^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\holli\data_reader.py”, line 12, in init
self.parameters = self.generate_list_of_parameters()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\holli\data_reader.py”, line 24, in generate_list_of_parameters
units=getattr(Units(), key.split(‘-’)[1]),
~~~~~~~~~~~~~~^^^
IndexError: list index out of range

enter image description here

Edit: Since the error seems to be related to the call for key.split I have added the full code snippet of this part from data_reader.py.

  def generate_list_of_parameters(self):
parameters = ListOfParameters([])
for key in self.data:
parameters.append(Parameter(value=[value for value in self.data[key]],
units=getattr(Units(), key.split('-')[1]),
name=key.split('-')[0]))
return parameters

2nd edit:

Using the below block of code the app is produced, but when I input a .csv data file I receive the error message

AttributeError: 'Data' object has no attribute 'generate_list_of_parameters'.

I have tried to set up the Data class as follows:

class Data:
def __init__(self, file, pandas=False):
    self.file_location = '' if pandas else file
    self.data = file if pandas else self.read_file(self.file_location)
    self.parameters = self.generate_list_of_parameters()

Solution

  • the error message that seems to be coming up, IndexError: list index out of range, is probably caused by trying to access an element of a list using an index that does not exist. In your file: data_reader.py this is happening at the line where key.split('-')[1] is called. the main problem and what you did wrong was you assumed that every key in the data has a hyphen (-) separating the parameter name and the unit type without checking if this format is consistently followed. and wiht the units you used getattr(Units(), key.split('-')[1]) to dynamically retrieve unit attributes. If the unit type did not exist in the Units class, this would raise an AttributeError. and last you had no error handling to manage situations where the unit type was not found in the Units class. here is the correct code(I hope): import pandas as pd from units import Units from convert import Convert, ConvertTemperature from parameter import Parameter, ListOfParameters from buckingham_pi_theorem.dimensional_analysis import DimensionalAnalysis

    class Data:
    def __init__(self, file, pandas=False):
            self.file_location = '' if pandas else 
    file
            self.data = file if pandas else 
    self.read_file(self.file_location)
            self.parameters = 
    self.generate_list_of_parameters()
    
    @staticmethod
    def read_file(file_location):
        data = pd.read_csv(file_location)
        return data
    
    def generate_list_of_parameters(self):
        parameters = ListOfParameters([])
        for key in self.data:
            try:
                print(f"Processing key: {key}")  # Debugging statement
                parts = key.split('-')
                if len(parts) > 1 and parts[1]:  # Check if there's a valid second part
                    unit_key = parts[1]
                    unit = getattr(Units, unit_key, None)
                    if unit is not None:
                        parameters.append(Parameter(value=[value for value in self.data[key]],
                                                    units=unit,
                                                    name=parts[0]))
                    else:
                        print(f"Attribute '{unit_key}' not found in Units class")
                else:
                    print(f"Key '{key}' does not have a valid second part after hyphen")
            except Exception as e:
                print(f"Error processing key '{key}': {e}")
        return parameters
    
    if __name__ == "__main__":
    experiment = Data("C:/Users/truma/Downloads/test - bernoulli_v2.csv")
    d = DimensionalAnalysis(experiment.parameters)
    d.plot()
    
    values = [80, 20, 9.8, 1, 1, 1]
    test = ListOfParameters([])
    for i, parameter in enumerate(experiment.parameters[1:]):
        test.append(Parameter(value=values[i], units=parameter.units, name=parameter.name))
    print('test', test)
    

    PLEASE NOTE THAT IMPORTS ARE NOT IN THIS CODE AND WILL HAVE TO BE ADDED!

    If you're using Streamlit and running into issues with importing the Data class from your file, make sure the file structure and import statements are correctly set up for example:

    import streamlit as st
    from data_reader import Data
    
    def main():
        st.title("Dimensional Analysis Tool")
        uploaded_file = st.file_uploader("Choose a CSV file", type="csv")
    if uploaded_file is not None:
        data = Data(uploaded_file, pandas=True)  # Assuming the CSV file is processed as a pandas DataFrame
        st.write(data.data)
        # Perform further analysis and display results
    
    if __name__ == "__main__":
        main()