Javier
Javier

Reputation: 513

How to remove periods of time in a dataframe?

I have this df:

       CODE    YEAR  MONTH DAY TMAX  TMIN   PP  BAD PERIOD 1 BAD PERIOD 2
9984   000130  1991    1    1  32.6  23.4  0.0     1991          1998
9985   000130  1991    1    2  31.2  22.4  0.0     NaN           NaN
9986   000130  1991    1    3  32.0   NaN  0.0     NaN           NaN
9987   000130  1991    1    4  32.2  23.0  0.0     NaN           NaN
9988   000130  1991    1    5  30.5  22.0  0.0     NaN           NaN
      ...   ...  ...  ...   ...   ...  ...
20118  000130  2018    9   30  31.8  21.2  NaN     NaN           NaN
30028  000132  1991    1    1  35.2   NaN  0.0     2005          2010
30029  000132  1991    1    2  34.6   NaN  0.0     NaN           NaN
30030  000132  1991    1    3  35.8   NaN  0.0     NaN           NaN
30031  000132  1991    1    4  34.8   NaN  0.0     NaN           NaN
      ...   ...  ...  ...   ...   ...   ...
50027  000132  2019    10   5  36.5   NaN  13.1    NaN           NaN
50028  000133  1991    1    1  36.2   NaN  0.0     1991          2010
50029  000133  1991    1    2  36.6   NaN  0.0     NaN           NaN
50030  000133  1991    1    3  36.8   NaN  5.0     NaN           NaN
50031  000133  1991    1    4  36.8   NaN  0.0     NaN           NaN
      ...   ...  ...  ...   ...   ...   ...
54456  000133  2019    10   5  36.5   NaN  12.1    NaN           NaN

I want to change the values ​​of the columns TMAX TMIN and PP to NaN, only of the periods specified in Bad Period 1 and Bad period 2 AND ONLY IN THEIR RESPECTIVE CODE. For example if I have Bad Period 1 equal to 1991 and Bad period 2 equal to 1998 I want all the values of TMAX, TMIN and PP that have code 000130 have NaN values since 1991 (bad period 1) to 1998 (bad period 2). I have 371 unique CODES in CODE column so i might use df.groupby("CODE").

Expected result after the change:

       CODE    YEAR  MONTH DAY TMAX   TMIN   PP  BAD PERIOD 1 BAD PERIOD 2
9984   000130  1991    1    1  NaN    NaN   NaN     1991          1998
9985   000130  1991    1    2  NaN    NaN   NaN     NaN           NaN
9986   000130  1991    1    3  NaN    NaN   NaN     NaN           NaN
9987   000130  1991    1    4  NaN    NaN   NaN     NaN           NaN
9988   000130  1991    1    5  NaN    NaN   NaN     NaN           NaN
      ...   ...  ...  ...   ...   ...  ...
20118  000130  2018    9   30  31.8   21.2  NaN     NaN           NaN
30028  000132  1991    1    1  35.2   NaN   0.0     2005          2010
30029  000132  1991    1    2  34.6   NaN   0.0     NaN           NaN
30030  000132  1991    1    3  35.8   NaN   0.0     NaN           NaN
30031  000132  1991    1    4  34.8   NaN   0.0     NaN           NaN
      ...   ...  ...  ...   ...   ...   ...
50027  000132  2019    10   5  36.5   NaN  13.1     NaN           NaN
50028  000133  1991    1    1  NaN    NaN   NaN     1991          2010
50029  000133  1991    1    2  NaN    NaN   NaN     NaN           NaN
50030  000133  1991    1    3  NaN    NaN   NaN     NaN           NaN
50031  000133  1991    1    4  NaN    NaN   NaN     NaN           NaN
      ...   ...  ...  ...   ...   ...   ...
54456  000133  2019    10   5  36.5   NaN  12.1     NaN           NaN

Upvotes: 0

Views: 201

Answers (1)

Ben.T
Ben.T

Reputation: 29635

you can propagate the values in your bad columns with ffill, if the non nan values are always at the first row per group of CODE and your data is ordered per CODE. If not, with groupby.transform and first. Then use mask to replace by nan where the YEAR is between your two bad columns once filled with the wanted value.

df_ = df[['BAD_1', 'BAD_2']].ffill()
#or more flexible df_ = df.groupby("CODE")[['BAD_1', 'BAD_2']].transform('first')
cols = ['TMAX', 'TMIN', 'PP']
df[cols] = df[cols].mask(df['YEAR'].ge(df_['BAD_1']) 
                         & df['YEAR'].le(df_['BAD_2']))
print(df)
       CODE  YEAR  MONTH  DAY  TMAX  TMIN    PP   BAD_1   BAD_2
9984    130  1991      1    1   NaN   NaN   NaN  1991.0  1998.0
9985    130  1991      1    2   NaN   NaN   NaN     NaN     NaN
9986    130  1991      1    3   NaN   NaN   NaN     NaN     NaN
9987    130  1991      1    4   NaN   NaN   NaN     NaN     NaN
9988    130  1991      1    5   NaN   NaN   NaN     NaN     NaN
20118   130  2018      9   30  31.8  21.2   NaN     NaN     NaN
30028   132  1991      1    1  35.2   NaN   0.0  2005.0  2010.0
30029   132  1991      1    2  34.6   NaN   0.0     NaN     NaN
30030   132  1991      1    3  35.8   NaN   0.0     NaN     NaN
30031   132  1991      1    4  34.8   NaN   0.0     NaN     NaN
50027   132  2019     10    5  36.5   NaN  13.1     NaN     NaN
50028   133  1991      1    1   NaN   NaN   NaN  1991.0  2010.0
50029   133  1991      1    2   NaN   NaN   NaN     NaN     NaN
50030   133  1991      1    3   NaN   NaN   NaN     NaN     NaN
50031   133  1991      1    4   NaN   NaN   NaN     NaN     NaN
54456   133  2019     10    5  36.5   NaN  12.1     NaN     NaN

Upvotes: 2

Related Questions