0

I'm trying to develop a class in python (Object Oriented). I want to keep the information of each defined object from that class into a pandas data frame, so at the end, I get a data frame that contains all of my object's info in it. How's that possible? What I've done until now is:

class SupplyChain:
def __init__(self, projectName, frame_type, NBeams, NColumns, TotalFrameWeight, Dist,
             RegisterationDate, EarliestPossibleSendTime, LatestSendTime, CurrentDay = 0):
    self.Name = projectName
    self.FrameType = frame_type
    self.TotalBeams = NBeams
    self.TotalColumns = NColumns
    self.TotalFrameWeight = TotalFrameWeight
    self.DistanceToSite = Dist
    self.DateofRegistration = RegisterationDate
    self.EarliestDelivery = self.DateofRegistration + EarliestPossibleSendTime
    self.LatestDelivery = self.DateofRegistration + LatestSendTime
    self.CurrentDate = CurrentDay
    self.FrameCost = self.TotalFrameWeight * 1000 * 31000
    if self.DistanceToSite <= 1000:
        self.TransportationCost = self.DistanceToSite * self.TotalFrameWeight * 20000
    else :
        self.TransportationCost = 1000 * TotalFrameWeight * 20000 + ( self.DistanceToSite - 1000 ) * self.TotalFrameWeight * 25000
    self.IsDelivered = 0
    self.DateofDelivery = 0
    self.StorageCost = 0.01 * self.FrameCost * (self.DateofDelivery - self.DateofRegistration)
    if self.DateofDelivery > self.LatestDelivery :
        self.DelayCost = 0.05 * self.FrameCost * (self.DateofDelivery - self.LatestDelivery)
    else:
        self.DelayCost = 0
    self.Profit = self.FrameCost + self.TransportationCost - self.StorageCost - self.DelayCost
    Columns = ["Name", "Type", "Number of Beams", "Number of Columns", "Total Weight","Distance to Site Location",
               "Date of Registeration", "Earliest Time to Deliver", "Latest Time to Deliver", "Current Day",
               "Frame Cost", "Transportation Cost", "Is Delivered?", "Date of Delivery", "Cost of Storage",
               "Cost of Delay", "Project Profit" ]
    self.df = pd.DataFrame(columns=Columns)
    
def PandasDataFrame(self):
    self.df.loc[len(self.df.index)] = [self.Name, self.FrameType, self.TotalBeams, self.TotalColumns,
                                       self.TotalFrameWeight, self.DistanceToSite, self.DateofRegistration,
                                       self.EarliestDelivery, self.LatestDelivery, self.CurrentDate, self.FrameCost, 
                                       self.TransportationCost, self.IsDelivered, self.DateofDelivery, 
                                       self.StorageCost, self.DelayCost, self.Profit]
    return self.df

I know it's not what I want, but I couldn't think of any other way.

FZL
  • 133
  • 6
  • 1
    So the idea is that you have a class `SupplyChain` that will be instantiated many times. And you want to keep a global dataframe that has the information about the parameters of each instantiation? – Luca Guarro Dec 10 '22 at 18:54
  • @Luca yes that is exactly what I want. – FZL Dec 10 '22 at 19:06
  • Just store the df outside of any method at the root level of the class and append to it during every call to __init__(). Assuming it doesn't need to be thread-safe or anything, that should work. – Dan Dec 11 '22 at 05:18
  • @Dan I tried to do as you said but couldn't get the desired outcome. Can you explain more specific, please? – FZL Dec 11 '22 at 07:38
  • @FZL you need a class variable that can store multiple instances (e.g., a list). See [this answer as an example.](https://stackoverflow.com/a/12102163/868044) The advantage of storing instances themselves vs. a representation of them (e.g., in a dataframe) is that you are maintaining a reference and not a copy, and therefore it is always current if the object changes after instantiation. You can then output it all to a dataframe on demand. But I don't know your constraints / use case so apply accordingly. – Dan Dec 11 '22 at 16:20

1 Answers1

0
  1. Create a dataframe outside the class with the desired columns which will be scoped to the module.
  2. Reference the dataframe from step 1 using the global keyword within the init function of SupplyChain.

Here is some code to give you an idea. You'll have to add the calculated parameters you made but other than that should be good to go.

import pandas as pd

class SupplyChain:
    def __init__(self, projectName, frame_type, NBeams, NColumns, TotalFrameWeight, Dist, RegisterationDate, EarliestPossibleSendTime, LatestSendTime, CurrentDay):
        self.projectName = projectName
        self.frame_type = frame_type
        self.NBeams = NBeams
        self.NColumns = NColumns
        self.TotalFrameWeight = TotalFrameWeight
        self.Dist = Dist
        self.RegisterationDate = RegisterationDate
        self.EarliestPossibleSendTime = EarliestPossibleSendTime
        self.LatestSendTime = LatestSendTime
        self.CurrentDay = CurrentDay
        
        # Append the parameters to the global dataframe
        global df
        df = df.append({"projectName": self.projectName, "frame_type": self.frame_type, "NBeams": self.NBeams, "NColumns": self.NColumns, "TotalFrameWeight": self.TotalFrameWeight, "Dist": self.Dist, "RegisterationDate": self.RegisterationDate, "EarliestPossibleSendTime": self.EarliestPossibleSendTime, "LatestSendTime": self.LatestSendTime, "CurrentDay": self.CurrentDay}, ignore_index=True)

# Create a global dataframe
df = pd.DataFrame(columns=["projectName", "frame_type", "NBeams", "NColumns", "TotalFrameWeight", "Dist", "RegisterationDate", "EarliestPossibleSendTime", "LatestSendTime", "CurrentDay"])

# Create an instance of the class
my_instance = SupplyChain("Project1", "frame_type1", 10, 5, 1000, 100, "2022-12-13", "2022-12-15", "2022-12-20", "2022-12-21")

Luca Guarro
  • 1,085
  • 1
  • 11
  • 25