AJG519
AJG519

Reputation: 3379

Creating class object from pandas series and applying methods

I have a function that reads in a bunch of raw data with some user-input and compiles it into a Pandas series. In the example below I call it create_data and it just builds a random Series of length n.

>>> def create_data(n):
...     return pd.Series(np.random.randint(1, 100, n))
... 
>>> 
>>> function_result=create_data(10)
>>> function_result
0    73
1    91
2    31
3    44
4    19
5    30
6    42
7    56
8    69
9    70
dtype: int32

Then I have a set of functions that want to be able to apply to this series. In this example, I create one that calculates the correlation between the series and its first-degree difference.

>>> def temporal_corr(x):
...     return pd.concat([x, x.shift()], 1).corr().iloc[0, 1]
... 

I can obviously just apply it to series by calling the function...

>>> temporal_corr(function_result)
0.38714413906049816

But let's say I have several different functions that I want to use on this series. Would it make more sense (or is it possible), to create a class that constructs an object using the function create_data and then have a set of functions within the class that can be applied as methods? I create a class and define this function below.

>>> class myobj:
...     def __init__(self, myobj):
...         self.myobj = myobj
...     
...     def temporal_corr(self):
...         return pd.concat([self.myobj, self.myobj.shift()], 1).corr().iloc[0, 1]
... 
>>> a = myobj(function_result)
>>> a.temporal_corr()
0.38714413906049816

What is the best way to have the class object myobj be created as a result of the function create_data? I would like to be able to call create_data and have the result be an object from which I can call temporal_corr().

Upvotes: 2

Views: 2636

Answers (2)

alichaudry
alichaudry

Reputation: 2743

If I understand your question correctly, I think you're looking to do the following:

import pandas as pd
import numpy as np


class MyObjMaker(object):

    def __init__(self, n):
        self.myobj = pd.Series(np.random.randint(1, 100, n))

    def temporal_corr(self):
        return pd.concat([self.myobj, self.myobj.shift()], 1).corr().iloc[0, 1]


def create_data(n):
    return MyObjMaker(n)

Here, the function create_data creates an object from the class, and that has your temporal_corr function. For example, I'd use it as follows:

In [2]: a = create_data(10)  # `a` is now an instance of MyObjMaker

In [4]: type(a)  # proof that `a` is now an instance of MyObjMaker
Out[4]: __main__.MyObjMaker

In [5]: a.temporal_corr()  # `temporal_corr` works
Out[5]: -0.18294239972101703

Jim's solution should be fine too, but it sub-classes off of pd.Series - if you don't need all the other methods in pd.Series then there's no point sub-classing off of it.

Upvotes: 2

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160427

Essentially you're looking for an object that acts like a Series but is more specialized, so, just create a class that inherits from pd.Series:

import pandas as pd
from numpy.random import randint

class mySeries(pd.Series):

    def __init__(self, n):
        super().__init__(randint(0, 100, n))  # initialize series

    # Add your custom methods:
    def temporal_corr(self):
        return pd.concat([self, self.shift()], 1).corr().iloc[0, 1]

Then, create_data can be your factory function for your specialized Series objects:

def create_data(n):
    return mySeries(n)

which you can extend and add checks according to your needs.

Upvotes: 2

Related Questions