1
\$\begingroup\$

This is an extension of my other question here. I have applied suggestions from 200_success in real-life problem at hand that deals with modelling extensible and combinable filter on Python Pandas dataframe structure. Is the code below reasonable and extensible, and are there areas I could improve this code on?

import pandas as pd

# Create df
######################################################################
data = [['tom', 'M', 10, 160], ['nick', 'M', 15, 155], ['juli', 'F', 14, 123], ['tom', 'M', 13, 170], 
    ['susan', 'F', 17, 99], ['trish', 'F', 45, 165], ['nash', 'M', 13, 213], ['nick', 'M', 15, 170],
    ['tom', 'M', 12, 188], ['trish', 'F', 16, 170]] 

df = pd.DataFrame(data, columns=['Name', 'Sex', 'Age', 'Weight'])

''' Name Sex      Age  Weight
0    tom   M       10     160
1   nick   M       15     155
2   juli   F       14     123
3    tom   M       13     170
4  susan   F       17      99
5  trish   F       45     165
6   nash   M       13     213
7   nick   M       15     170
8    tom   M       12     188
9  trish   F       16     170'''

# Primitive filters
######################################################################
def age_at_least(var='Age', threshold=12):
    def execute(df):
        return df[df[var]>=threshold] 
    return execute

def age_at_max(var='Age', threshold=30):
    def execute(df):
        return df[df[var]<=threshold] 
    return execute

def remove_by_sex(var='Sex', threshold='M'):
    def execute (df):
        return df[df[var]!=threshold] 
    return execute

def weight_at_least(var='Weight', threshold=50):
    def execute (df):
        df['Weight_kg'] = df[var].apply(lb_to_kg)
        return df[df['Weight_kg']>=threshold] 
    return execute

def lb_to_kg(lb):
    return lb/2.20462

# Higher order function
######################################################################
def compose(*filters):
    def composed(df):
        for f in filters:
            if f is not None:
                df = f(df)
        return df
    return composed

def item_filtering(
        filter_age_at_least = age_at_least(threshold=15),
        filter_general = compose(age_at_max(), remove_by_sex(threshold='F')),
        filter_specific = weight_at_least(),
    ):
    return compose(filter_age_at_least, filter_general, filter_specific)

# Demonstration
######################################################################
ob = item_filtering()
print(ob(df))

# Output
'''    Name Sex  Age  Weight  Weight_kg
    1  nick   M   15     155  70.306901
    7  nick   M   15     170  77.110795
'''
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.