Отметить только первую строку, где условие выполняется в DataFrame - PullRequest
9 голосов
/ 27 марта 2019

У меня есть следующий DataFrame df, который можно создать следующим образом:

date_today = datetime.now().date()
days = pd.date_range(date_today, date_today + timedelta(19), freq='D')
x = np.arange(0,2*np.pi,0.1*np.pi)   # start,stop,step
y = np.sin(x)
df = pd.DataFrame({'dates': days, 'vals': y, 'is_hit': abs(y)>0.9})
df = df.set_index('dates')

И это выглядит так:

            is_hit          vals
dates                           
2019-03-27   False  0.000000e+00
2019-03-28   False  3.090170e-01
2019-03-29   False  5.877853e-01
2019-03-30   False  8.090170e-01
2019-03-31    True  9.510565e-01
2019-04-01    True  1.000000e+00
2019-04-02    True  9.510565e-01
2019-04-03   False  8.090170e-01
2019-04-04   False  5.877853e-01
2019-04-05   False  3.090170e-01
2019-04-06   False  1.224647e-16
2019-04-07   False -3.090170e-01
2019-04-08   False -5.877853e-01
2019-04-09   False -8.090170e-01
2019-04-10    True -9.510565e-01
2019-04-11    True -1.000000e+00
2019-04-12    True -9.510565e-01
2019-04-13   False -8.090170e-01
2019-04-14   False -5.877853e-01
2019-04-15   False -3.090170e-01

Я хочу отметить строки, гдеусловие is_hit впервые True, так что ожидаемый новый столбец hit_first будет:

           is_hit          vals  hit_first
dates                                      
2019-03-27   False  0.000000e+00      False
2019-03-28   False  3.090170e-01      False
2019-03-29   False  5.877853e-01      False
2019-03-30   False  8.090170e-01      False
2019-03-31    True  9.510565e-01       True
2019-04-01    True  1.000000e+00      False
2019-04-02    True  9.510565e-01      False
2019-04-03   False  8.090170e-01      False
2019-04-04   False  5.877853e-01      False
2019-04-05   False  3.090170e-01      False
2019-04-06   False  1.224647e-16      False
2019-04-07   False -3.090170e-01      False
2019-04-08   False -5.877853e-01      False
2019-04-09   False -8.090170e-01      False
2019-04-10    True -9.510565e-01       True
2019-04-11    True -1.000000e+00      False
2019-04-12    True -9.510565e-01      False
2019-04-13   False -8.090170e-01      False
2019-04-14   False -5.877853e-01      False
2019-04-15   False -3.090170e-01      False

Как создать этот столбец hit_first?

Ответы [ 4 ]

11 голосов
/ 27 марта 2019

Мое предложение:

df['hit_first'] = df['is_hit'] & (~df['is_hit']).shift(1)
3 голосов
/ 27 марта 2019

Я тоже, думаю, вы можете сделать это так:

df['is_hit'].astype(int).diff() == 1

Выход:

dates
2019-03-27    False
2019-03-28    False
2019-03-29    False
2019-03-30    False
2019-03-31     True
2019-04-01    False
2019-04-02    False
2019-04-03    False
2019-04-04    False
2019-04-05    False
2019-04-06    False
2019-04-07    False
2019-04-08    False
2019-04-09    False
2019-04-10     True
2019-04-11    False
2019-04-12    False
2019-04-13    False
2019-04-14    False
2019-04-15    False
Name: is_hit, dtype: bool

Тайминги:

%timeit df['is_hit'] & (~df['is_hit']).shift(1)
1.13 ms ± 5.63 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df['is_hit'].ne(df['is_hit'].shift()) & df['is_hit']
908 µs ± 9.53 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df['is_hit'].astype(int).diff() == 1
689 µs ± 8.24 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
3 голосов
/ 27 марта 2019

Использовать Series.shift в цепочке с & для побитового AND:

df['hit_first'] = df['is_hit'].ne(df['is_hit'].shift()) & df['is_hit']
print (df)
                    vals  is_hit  hit_first
dates                                      
2019-03-27  0.000000e+00   False      False
2019-03-28  3.090170e-01   False      False
2019-03-29  5.877853e-01   False      False
2019-03-30  8.090170e-01   False      False
2019-03-31  9.510565e-01    True       True
2019-04-01  1.000000e+00    True      False
2019-04-02  9.510565e-01    True      False
2019-04-03  8.090170e-01   False      False
2019-04-04  5.877853e-01   False      False
2019-04-05  3.090170e-01   False      False
2019-04-06  1.224647e-16   False      False
2019-04-07 -3.090170e-01   False      False
2019-04-08 -5.877853e-01   False      False
2019-04-09 -8.090170e-01   False      False
2019-04-10 -9.510565e-01    True       True
2019-04-11 -1.000000e+00    True      False
2019-04-12 -9.510565e-01    True      False
2019-04-13 -8.090170e-01   False      False
2019-04-14 -5.877853e-01   False      False
2019-04-15 -3.090170e-01   False      False
0 голосов
/ 27 марта 2019

Также это можно сделать, используя простую разницу между сериями и сериями, сдвинутыми на 1 период:

df['hit_first'] = df['is_hit']-df['is_hit'].shift()==1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...