I have the following DataFrame, where Value refers to my observations, and Criterion indicates, when a Value should be set to np.nan.
| Value | Criterion |
|---|---|
| 3 | 0 |
| 3 | 0 |
| 5 | 1 |
| 7 | 0 |
| 2 | 0 |
| 2 | 0 |
| 8 | 1 |
| 8 | 0 |
| 8 | 0 |
| 1 | 0 |
Whenever Criterion is equal to 1, I want to set the Value in the same row, as well as all consecutive Values to zero until Value changes. The desired output should look like this.
| Value | Criterion |
|---|---|
| 3 | 0 |
| 3 | 0 |
| nan | 1 |
| 7 | 0 |
| 2 | 0 |
| 2 | 0 |
| nan | 1 |
| nan | 0 |
| nan | 0 |
| 1 | 0 |
CodePudding user response:
Create groups by consecutive values in Value column and test if at least one 1 in Criterion, then set NaN per group in Series.mask:
s = df['Value'].ne(df['Value'].shift()).cumsum()
df['Value'] = df['Value'].mask(df['Criterion'].groupby(s).transform('any'))
print (df)
Value Criterion
0 3.0 0
1 3.0 0
2 NaN 1
3 7.0 0
4 2.0 0
5 2.0 0
6 NaN 1
7 NaN 0
8 NaN 0
9 1.0 0
Or if need test first value is 1 per consecutive groups in column Criterion use:
s= df['Value'].ne(df['Value'].shift()).cumsum()
df['Value'] = df['Value'].mask(df['Criterion'].groupby(s).transform('first').eq(1))
