Python pandas column operations

Viewed 128

I'm trying to do some columnar operations on a dataframe and I'm stuck at one point. I'm new to pandas and now I'm unable to figure how to do this.

So wherever there is a "Yes" value in "Prevous_Line_Has_Br" buffer should be added to the "OldTop" value but whenever there is a "No" in between it should stop incrementing, take the previous row value and start incrementing when there is a "Yes" again.

I have tried something like this

            temp_df["CheckBr"] = temp_df["Prevous_Line_Has_Br"].shift(1)
            temp_df["CheckBr"] = temp_df["CheckBr"].fillna("dummy")
            temp_df.insert(0, 'New_ID', range(0, 0 + len(temp_df)))
            temp_df["NewTop"] = "NoIncr"
            temp_df["MyTop"] = 0

            temp_df.loc[(temp_df["Prevous_Line_Has_Br"] == "Yes") & (temp_df["CheckBr"] == "Yes"), "NewTop"] = "Incr"
            temp_df.loc[(temp_df["Prevous_Line_Has_Br"] == "Yes") & (temp_df["CheckBr"] == "No"), "NewTop"] = "Incr"
            temp_df.loc[(temp_df["Prevous_Line_Has_Br"] == "Yes") & (temp_df["CheckBr"] == "dummy"), "NewTop"] = "Incr"


            temp_df.loc[(temp_df["NewTop"]=="Incr"),"MyTop" ] = new_top + (temp_df.New_ID * temp_df.buffer)
            temp_df.loc[(temp_df["CheckBr"] == "Yes") & (temp_df["MyTop"] == 0), "MyTop"] = temp_df["MyTop"].shift(1)

This is giving me the following output to achieve the same without the for loop: Modified dataframe

Can someone please help achieve the values in the original dataframe using pandas?

This is what I want to achieve finally.. enter image description here

2 Answers

This would be fairly easy to do if you moved away from pandas, and treated the columns as just lists. If you want to still use the apply method, you can use to decorator to keep track of the last row.

def apply_func_decorator(func):
    prev_row = {}
    def wrapper(curr_row, **kwargs):
        val = func(curr_row, prev_row)
        prev_row.update(curr_row)
        prev_row[new_col] = val
        return val
    return wrapper

@apply_func_decorator
def add_buffer_and_top(curr_row, prev_row):
    if curr_row.Prevous_Line_Has_Br == 'Yes':
        if prev_row:
            return curr_row.buffer + prev_row['NewTop']
        return curr_row.buffer + prev_row['OldTop']
    return prev_row['NewTop']

temp_df['NewTop'] = 0
temp_df['NewTop'] = temp_df.apply(add_buffer_and_top, axis=1)

This is how I achieved the output I desired

            m = temp_df['Prevous_Line_Has_Br'].eq('Yes')

            temp_df['New_ID'] = m.cumsum().where(m,np.nan)

            temp_df["New_ID"] = temp_df["New_ID"].ffill()

            temp_df["Top"] = temp_df['Old_Top'] + (temp_df['New_ID'] * temp_df['buffer'])

Column New_ID was incremented only when there was a value 'Yes' in column Previous_Line_Has_br.

Related