1

I have an array of dataframe objects (columns of a larger dataframe) that I am passing into the Dataframe_Builder_Update class. I am able to successfully update the date and associated calculation of the column objects with this code:

[setattr(obj, 'date', '12/29/2019') for obj in dataframe_builder_obj.column_builders]

but the build_dataframe() class is not updating.

class Dataframe_Builder_Update():

    def __init__(self, column_builders):
        self._column_builders = column_builders
        self.build_dataframe()
    
    def build_dataframe(self):
        self.result_df = pd.DataFrame()

        for column_builder in self._column_builders:
            if not column_builder.group:
                self.result_df = pd.concat([self.result_df, column_builder.calculated_output], axis=0)
            elif column_builder.group:
                self.result_df = pd.concat([self.result_df, column_builder.calculated_output], axis=1)

    @property
    def column_builders(self):
        return self._column_builders

    @column_builders.setter
    def column_builders(self, new_column_builders):
        self._column_builders = new_column_builders
        self.build_dataframe() 


dataframe_builder_obj = Dataframe_Builder_Update(my_arr)
dataframe_builder_obj.result_df

old dataframe output (works correctly)

[setattr(obj, 'date', '12/29/2019') for obj in dataframe_builder_obj.column_builders]
dataframe_builder_obj.result_df

supposed to be the new dataframe output (does not work)

[setattr(obj, 'date', '12/29/2019') for obj in dataframe_builder_obj.column_builders]
dataframe_builder_obj.build_dataframe()

this works correctly but I just don't want to have to explicitly call the method

2
  • I don't understand why do you have a comprehension... and what do you expect from it. With setattr you are adding the same attribute and value to the instance at every iteration
    – cards
    Commented Nov 29, 2023 at 21:12
  • 1
    Yes that is the point. Each of the objects in the column_builders array performs a calculation on a dataframe in the object. I would like to update each object's date in the array to the new date. This then changes the .calculated_output for each object. The Dataframe Builder class simply combines the individual .calculated_output dataframes. Commented Nov 29, 2023 at 21:18

1 Answer 1

1
class Dataframe_Builder():
    def __init__(self, column_builders):
        self._column_builders = column_builders  # pass in column builders object array
        self._result_df = self.build_dataframe()

    @property
    def column_builders(self):
        return self._column_builders

    @property
    def result_df(self):
        return self._result_df

    @column_builders.setter
    def column_builders(self, new_column_builders):
        self._column_builders = new_column_builders
        self.update_dataframe()

    def build_dataframe(self):
        result_df = pd.DataFrame()

        for obj in self._column_builders:
            if not obj.group:
                result_df = pd.concat([result_df, obj.calculated_output], axis=0)
            elif obj.group:
                result_df = pd.concat([result_df, obj.calculated_output], axis=1)

        return result_df

    def update_dataframe(self):
        self._result_df = self.build_dataframe()
    
class Table_Builder():
    
    def __init__(self, df_builders: list, stack_horizontal=None, stack_vertical=None):
        self.df_builders = df_builders
        self.stack_horizontal = stack_horizontal
        self.stack_vertical = stack_vertical
        
        self.result_df = self.build_table(self.stack_horizontal, self.stack_vertical)

    def build_table(self, stack_horizontal=None, stack_vertical=None):
        result_df = pd.DataFrame()

        for obj in self.df_builders:
            if stack_vertical:
                result_df = pd.concat([result_df, obj.result_df], axis=0)
            elif stack_horizontal:
                result_df = pd.concat([result_df, obj.result_df], axis=1)

        return result_df
    
    def update_dates(self, new_date):
        for df_obj in self.df_builders:
            for col_obj in df_obj.column_builders:
                setattr(col_obj, 'date', new_date)
            df_obj.update_dataframe()
        
        # Build new table
        self.result_df = self.build_table(self.stack_horizontal, self.stack_vertical)
result_df.update_dates('3/30/2019')
result_df.result_df
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.