Панды - условная колонка с раздвижным окном - PullRequest
2 голосов
/ 17 мая 2019

У меня есть df с двумя столбцами - метками времени и текстом.Я пытаюсь пометить данные метками True / false (1/0).Условие состоит в том, что ЕСЛИ в тексте есть слово «ошибка», то все записи должны быть за 3-4 часа ДО того, как запись получит метку 1, а остальные 0. Например.из df вот так:

time   text
15:00  a-ok
16:01  fine
17:00  kay
18:00  uhum
19:00  doin well
20:00  is error
20:05  still error
21:00  fine again

Должен быть преобразован в:

time   text       error coming
15:00  a-ok       0
16:01  fine       1
17:00  kay        1
18:00  uhum       1
19:00  doin well  1
20:00  is error   0
20:05  still error0
21:00  fine again 0

Я читал кое-что о сдвижных окнах с .rolling, но у меня возникли проблемы с объединением всего этого.

1 Ответ

0 голосов
/ 17 мая 2019

Идея заключается в преобразовании времени в timedeltas, фильтрации timedeltas с ошибками и для каждого значения создайте маску с logical_or.reduce, цепную маску с инвертированными m1 для значений error s и преобразуйте в целое число для True/False в 1/0 отображение:

td = pd.to_timedelta(df['time'].astype(str) + ':00')

m1 = df['text'].str.contains('error')
v = td[m1]
print (v)
5   20:00:00
6   20:05:00
Name: time, dtype: timedelta64[ns]

m2 = np.logical_or.reduce([td.between(x - pd.Timedelta(4, unit='h'), x) for x in v])
df['error coming'] = (m2 & ~m1).astype(int)
print (df)
    time         text  error coming
0  15:00         a-ok             0
1  16:01         fine             1
2  17:00          kay             1
3  18:00         uhum             1
4  19:00    doin well             1
5  20:00     is error             0
6  20:05  still error             0
7  21:00   fine again             0

EDIT:

df['time'] = pd.to_datetime(df['time'])
print (df)
                 time         text
0 2019-01-26 15:00:00         a-ok
1 2019-01-26 16:01:00         fine
2 2019-01-26 17:00:00          kay
3 2019-01-26 18:00:00         uhum
4 2019-01-26 19:00:00    doin well
5 2019-01-26 20:00:00     is error
6 2019-01-26 20:05:00  still error
7 2019-01-26 21:00:00   fine again

print (df.dtypes)
time    datetime64[ns]
text            object
dtype: object

m1 = df['text'].str.contains('error')
v = df.loc[m1, 'time']
print (v)
5   2019-01-26 20:00:00
6   2019-01-26 20:05:00
Name: time, dtype: datetime64[ns]

m2 = np.logical_or.reduce([df['time'].between(x - pd.Timedelta(4, unit='h'), x) for x in v])
df['error coming'] = (m2 & ~m1).astype(int)
print (df)
                 time         text  error coming
0 2019-01-26 15:00:00         a-ok             0
1 2019-01-26 16:01:00         fine             1
2 2019-01-26 17:00:00          kay             1
3 2019-01-26 18:00:00         uhum             1
4 2019-01-26 19:00:00    doin well             1
5 2019-01-26 20:00:00     is error             0
6 2019-01-26 20:05:00  still error             0
7 2019-01-26 21:00:00   fine again             0

Векторизованное решение:

m1 = df['text'].str.contains('error')
v = df.loc[m1, 'time']
print (v)
5   2019-01-26 20:00:00
6   2019-01-26 20:05:00
Name: time, dtype: datetime64[ns]

a = v - pd.Timedelta(4, unit='h')
m = (a.values < df['time'].values[:, None]) & (v.values > df['time'].values[:, None])
df['error coming'] = (m.any(axis=1) & ~m1).astype(int)
print (df)
                 time         text  error coming
0 2019-01-26 15:00:00         a-ok             0
1 2019-01-26 16:01:00         fine             1
2 2019-01-26 17:00:00          kay             1
3 2019-01-26 18:00:00         uhum             1
4 2019-01-26 19:00:00    doin well             1
5 2019-01-26 20:00:00     is error             0
6 2019-01-26 20:05:00  still error             0
7 2019-01-26 21:00:00   fine again             0
...