1

I am new to Python. I am trying to pass a dataframe to a class. My class has 2 methods. I would like to call them as a chained methods. Both the methods return dataframes and one is the input to other like the code return below.

import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})
class Foo(pd.DataFrame):
    def __init__(self, df):
        self.df=df
    def bar(self):
        print ("Foo.bar called")
        df=self.df.rolling(window=len(df),min_periods=0).sum()
        return df
    def baz(self):
        print ("Foo.baz called")
        df=self.df.rolling(window=len(df),min_periods=0).sum()
        return df

Then executed as below

foo = Foo(df)
foo1 = foo.bar().baz()
foo2 = foo.baz().bar()
print(foo1, foo2)

With this code I am getting the below error

---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-143-090d3a6b6de4> in <module>
     11         df2=self.df2.rolling(window=len(df2),min_periods=0).sum()
     12         return df2
---> 13 foo = Foo(df)
     14 # foo.df=df
     15 # print(foo.df)

<ipython-input-143-090d3a6b6de4> in __init__(self, df2)
      2 class Foo(pd.DataFrame):
      3     def __init__(self, df2):
----> 4         self.df2=df2
      5     def bar(self):
      6         print ("Foo.bar called")

~/opt/anaconda3/lib/python3.8/site-packages/pandas/core/generic.py in __setattr__(self, name, value)
   5162         else:
   5163             try:
-> 5164                 existing = getattr(self, name)
   5165                 if isinstance(existing, Index):
   5166                     object.__setattr__(self, name, value)

~/opt/anaconda3/lib/python3.8/site-packages/pandas/core/generic.py in __getattr__(self, name)
   5135             return object.__getattribute__(self, name)
   5136         else:
-> 5137             if self._info_axis._can_hold_identifiers_and_holds_name(name):
   5138                 return self[name]
   5139             return object.__getattribute__(self, name)

~/opt/anaconda3/lib/python3.8/site-packages/pandas/core/generic.py in __getattr__(self, name)
   5135             return object.__getattribute__(self, name)
   5136         else:
-> 5137             if self._info_axis._can_hold_identifiers_and_holds_name(name):
   5138                 return self[name]
   5139             return object.__getattribute__(self, name)

... last 2 frames repeated, from the frame below ...

~/opt/anaconda3/lib/python3.8/site-packages/pandas/core/generic.py in __getattr__(self, name)
   5135             return object.__getattribute__(self, name)
   5136         else:
-> 5137             if self._info_axis._can_hold_identifiers_and_holds_name(name):
   5138                 return self[name]
   5139             return object.__getattribute__(self, name)

RecursionError: maximum recursion depth exceeded while calling a Python object

My intention is to pass the output of one method should be passed as input to another method. That is I am passing a data frame to my bar() method returns a data frame, this data frame should be passed as input to my baz() method. This baz() method also return a data frame. Hence, I want to call these repeatedly as a chain. I have a sample code without using dataframes below. I am trying to apply the similar logic to dataframes.

class Foo1(object):
    
    def bar(self):
        print ("Foo.bar called")
        return self
    def baz(self):
        print ("Foo.baz called")
        return self
foo = Foo1()
foo2 = foo.bar().baz()
print (" id(foo):", id(foo))
print ("id(foo2):", id(foo2))
foo2 = foo.baz().bar()

I would request anyone kindly help me to understand why is it going into infinite loop.

Thanks in advance.

1
  • 1
    Class argument should be empty: class Foo() Commented Jan 18, 2021 at 6:33

2 Answers 2

2

You have multiple errors:

  1. Class argument should be empty
  2. In the methods bar and baz you're calling df instead of self.df
  3. If you want to apply a method over a method output, it has to be a Foo instance.

Here's a working code:

import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})

class Foo():
    def __init__(self, df):
        self.df=df
    def bar(self):
        print ("Foo.bar called")
        df=self.df.rolling(window=len(self.df),min_periods=0).sum()
        return Foo(df)
    def baz(self):
        print ("Foo.baz called")
        df=self.df.rolling(window=len(self.df),min_periods=0).sum()
        return Foo(df)

foo = Foo(df)
foo1 = foo.bar().baz()
foo2 = foo.baz().bar()
print(foo1, foo2)
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your quick response. I am sorry. I haven’t specified why I was calling like that. My intention is to pass the output of one method should be passed as input to another method. That is I am passing a data frame to my bar() method returns a data frame, this data frame should be passed as input to my baz() method. This baz() method also return a data frame. Hence, I want to call these repeatedly as a chain.
@SreenathReddy check it now, is that what you want?
0

As the @master pointed out in the comment, you should not use an argument in the class, i.e. you should not inherit from pd.Dataframe. Also you reference to df and not to self.df in your methods.

A working version of your code:

import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]})
class Foo:
    def __init__(self, df):
        self.df=df
    def bar(self):
        print ("Foo.bar called")
        df=self.df.rolling(window=len(self.df),min_periods=0).sum()
        return df
    def baz(self):
        print ("Foo.baz called")
        df=self.df.rolling(window=len(self.df),min_periods=0).sum()
        return df

Also you somewhat called the method twice foo.bar().baz() instead of foo.bar(). You return only a df not a Foo class in your methods. So you should call it like this:

    foo = Foo(df)
    foo1 = foo.bar()
    foo2 = foo.baz()
    print(foo1, foo2)

1 Comment

Thank you very much for your quick response. I am sorry. I haven’t specified why I was calling like that. My intention is to pass the output of one method should be passed as input to another method. That is I am passing a data frame to my bar() method returns a data frame, this data frame should be passed as input to my baz() method. This baz() method also return a data frame. Hence, I want to call these repeatedly as a chain.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.