Search code examples
python-3.xpandasseriesmulti-index

Change pandas.Series values based on a particular level of its MultiIndex


I've got a pd.Series as the following:

WORKER   DATE         PROFILE  HOURS
0000123  2023-01-30   R01      8.0
0000123  2023-01-31   R01      8.0
0000123  2023-02-01   T05      8.0
0000123  2023-02-02   T09      8.0
...

MultiIndex([('0000123','2023-01-30','R01'),
            ('0000123','2023-01-30','R01'),
            ('0000123','2023-01-30','R01'),
            ('0000123','2023-01-30','R01')],
           names=['WORKER', 'DATE', 'PROFILE'], lenght=839)

The series comes from other scripting parts, and basically is the result of a df.groupby, grouped and summerized by these values.

I'd like to have - possibily - a single/few lines of code that:

IF (HOURS == 8) AND (PROFILE == T05 OR T09)
THEN HOURS == 7

By now, I tried a lot of pandas methods but I run always in an error.

I think my error is because PROFILE is a multiindex level, but don't know how to manage this double condition both on index AND value.


Solution

  • Create mask by Series.eq with Index.get_level_values and Index.isin, chain by & for bitwise AND and pass to Series.loc:

    mux = pd.MultiIndex.from_tuples([('0000123','2023-01-30','R01'),
                                    ('0000123','2023-01-30','R01'),
                                    ('0000123','2023-01-30','T05'),
                                    ('0000123','2023-01-30','T06')],
                                    names=['WORKER', 'DATE', 'PROFILE'])
    s = pd.Series([8.0]*4, index=mux)
    
    print (s)
    WORKER   DATE        PROFILE
    0000123  2023-01-30  R01        8.0
                         R01        8.0
                         T05        8.0
                         T06        8.0
    dtype: float64
    
    m = s.eq(8) & s.index.get_level_values('PROFILE').isin(['T05','T06'])
    s.loc[m] = 7
    print (s)
    
    WORKER   DATE        PROFILE
    0000123  2023-01-30  R01        8.0
                         R01        8.0
                         T05        7.0
                         T06        7.0
    dtype: float64