Pandas — условный столбец со скользящим окном

У меня есть 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, но мне трудно собрать все это воедино.

Может ли он появиться во многих строках?

yatu 17.05.2019 12:51

да. Я изменю вопрос, чтобы отразить его.

lte__ 17.05.2019 12:52

Это очень сложно :) посмотрю позже, надеюсь, вы получите ответ достаточно скоро.

yatu 17.05.2019 12:55
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
3
204
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Идея состоит в том, чтобы преобразовать время в временные дельты, отфильтровать временные дельты с ошибками и для каждого значения создать маску с logical_or.reduce, цепную маску с инвертированным m1, чтобы избежать значений errors, и преобразовать в целое число для отображения 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

Обновлено:

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

@lte__ - тогда измените td = pd.to_timedelta(df['time'].astype(str) + ':00') на td = pd.to_datetime(df['time'])

jezrael 17.05.2019 13:13

Если я сделаю это, я получу TypeError: dtype datetime64[ns, UTC] cannot be converted to timedelta64[ns], а если я сделаю td = pd.to_timedelta(df_full['time'].values.astype('datetime64[ns‌​]')), то в итоге получу AttributeError: 'TimedeltaIndex' object has no attribute 'between'... Что я упускаю?

lte__ 17.05.2019 13:19

Другие вопросы по теме