Search code examples
pythonpandasnumpyconditional-statementsmulti-index

Pandas Multi-index set value based on three different condition


The objective is to create a new multiindex column based on 3 conditions of the column (B)

Condition for B

if B<0
  CONDITION_B='l`
elif B<-1
  CONDITION_B='L`
else
  CONDITION_B='g`

Naively, I thought, we can simply create two different mask and replace the value as suggested

# Handle CONDITION_B='l` and CONDITION_B='g`

mask_2 = df.loc[:,idx[:,'B']]<0
appenddf_2=mask_2.replace({True:'g',False:'l'}).rename(columns={'A':'iv'},level=1)

and then

# CONDITION_B='L`
mask_33 = df.loc[:,idx[:,'B']]<-0.1
appenddf_2=mask_33.replace({True:'G'}).rename(columns={'A':'iv'},level=1)

As expected, this will throw an error

TypeError: sequence item 1: expected str instance, bool found

May I know how to handle the 3 different condition

Expected output

ONE TWO
B   B
g   L
l   l
l   g
g   l
L   L

The code to produce the error is

import pandas as pd
import numpy as np

np.random.seed(3)
arrays = [np.hstack([['One']*2, ['Two']*2]) , ['A', 'B', 'A', 'B']]
columns = pd.MultiIndex.from_arrays(arrays)
df=  pd.DataFrame(np.random.randn(5, 4), columns=list('ABAB'))

df.columns = columns

idx = pd.IndexSlice



mask_2 = df.loc[:,idx[:,'B']]<0
appenddf_2=mask_2.replace({True:'g',False:'l'}).rename(columns={'A':'iv'},level=1)
mask_33 = df.loc[:,idx[:,'B']]<-0.1
appenddf_2=mask_33.replace({True:'G'}).rename(columns={'A':'iv'},level=1)

Solution

  • IIUC:

    np.select() is ideal in this case:

    conditions=[
        df.loc[:,idx[:,'B']].lt(0) & df.loc[:,idx[:,'B']].gt(-1),
        df.loc[:,idx[:,'B']].lt(-1),
        df.loc[:,idx[:,'B']].ge(0)
    ]
    labels=['l','L','g']
    out=pd.DataFrame(np.select(conditions,labels),columns=df.loc[:,idx[:,'B']].columns)
    

    OR

    via np.where():

    s=np.where(df.loc[:,idx[:,'B']].lt(0) & df.loc[:,idx[:,'B']].gt(-1),'l',np.where(df.loc[:,idx[:,'B']].lt(-1),'L','g'))
    out=pd.DataFrame(s,columns=df.loc[:,idx[:,'B']].columns)
    

    output of out:

       One  Two
        B   B
    0   g   L
    1   l   l
    2   l   g
    3   g   l
    4   L   L